cjson
fuzzing
inputs
test1 test10 test11 test2 test3 test3.bu test3.uf test3.uu test4 test5 test6 test7 test8 test9library_config
cJSONConfig.cmake.in cJSONConfigVersion.cmake.in libcjson.pc.in libcjson_utils.pc.in uninstall.cmaketests
inputs
test1 test1.expected test10 test10.expected test11 test11.expected test2 test2.expected test3 test3.expected test4 test4.expected test5 test5.expected test6 test7 test7.expected test8 test8.expected test9 test9.expectedjson-patch-tests
.editorconfig .gitignore .npmignore README.md cjson-utils-tests.json package.json spec_tests.json tests.jsonunity
auto
colour_prompt.rb colour_reporter.rb generate_config.yml generate_module.rb generate_test_runner.rb parse_output.rb stylize_as_junit.rb test_file_filter.rb type_sanitizer.rb unity_test_summary.py unity_test_summary.rb unity_to_junit.pydocs
ThrowTheSwitchCodingStandard.md UnityAssertionsCheatSheetSuitableforPrintingandPossiblyFraming.pdf UnityAssertionsReference.md UnityConfigurationGuide.md UnityGettingStartedGuide.md UnityHelperScriptsGuide.md license.txtexamples
unity_config.hcurl
.github
scripts
cleancmd.pl cmp-config.pl cmp-pkg-config.sh codespell-ignore.words codespell.sh distfiles.sh pyspelling.words pyspelling.yaml randcurl.pl requirements-docs.txt requirements-proselint.txt requirements.txt shellcheck-ci.sh shellcheck.sh spellcheck.curl trimmarkdownheader.pl typos.sh typos.toml verify-examples.pl verify-synopsis.pl yamlcheck.sh yamlcheck.yamlworkflows
appveyor-status.yml checkdocs.yml checksrc.yml checkurls.yml codeql.yml configure-vs-cmake.yml curl-for-win.yml distcheck.yml fuzz.yml http3-linux.yml label.yml linux-old.yml linux.yml macos.yml non-native.yml windows.ymlCMake
CurlSymbolHiding.cmake CurlTests.c FindBrotli.cmake FindCares.cmake FindGSS.cmake FindGnuTLS.cmake FindLDAP.cmake FindLibbacktrace.cmake FindLibgsasl.cmake FindLibidn2.cmake FindLibpsl.cmake FindLibssh.cmake FindLibssh2.cmake FindLibuv.cmake FindMbedTLS.cmake FindNGHTTP2.cmake FindNGHTTP3.cmake FindNGTCP2.cmake FindNettle.cmake FindQuiche.cmake FindRustls.cmake FindWolfSSL.cmake FindZstd.cmake Macros.cmake OtherTests.cmake PickyWarnings.cmake Utilities.cmake cmake_uninstall.in.cmake curl-config.in.cmake unix-cache.cmake win32-cache.cmakedocs
cmdline-opts
.gitignore CMakeLists.txt MANPAGE.md Makefile.am Makefile.inc _AUTHORS.md _BUGS.md _DESCRIPTION.md _ENVIRONMENT.md _EXITCODES.md _FILES.md _GLOBBING.md _NAME.md _OPTIONS.md _OUTPUT.md _PROGRESS.md _PROTOCOLS.md _PROXYPREFIX.md _SEEALSO.md _SYNOPSIS.md _URL.md _VARIABLES.md _VERSION.md _WWW.md abstract-unix-socket.md alt-svc.md anyauth.md append.md aws-sigv4.md basic.md ca-native.md cacert.md capath.md cert-status.md cert-type.md cert.md ciphers.md compressed-ssh.md compressed.md config.md connect-timeout.md connect-to.md continue-at.md cookie-jar.md cookie.md create-dirs.md create-file-mode.md crlf.md crlfile.md curves.md data-ascii.md data-binary.md data-raw.md data-urlencode.md data.md delegation.md digest.md disable-eprt.md disable-epsv.md disable.md disallow-username-in-url.md dns-interface.md dns-ipv4-addr.md dns-ipv6-addr.md dns-servers.md doh-cert-status.md doh-insecure.md doh-url.md dump-ca-embed.md dump-header.md ech.md egd-file.md engine.md etag-compare.md etag-save.md expect100-timeout.md fail-early.md fail-with-body.md fail.md false-start.md follow.md form-escape.md form-string.md form.md ftp-account.md ftp-alternative-to-user.md ftp-create-dirs.md ftp-method.md ftp-pasv.md ftp-port.md ftp-pret.md ftp-skip-pasv-ip.md ftp-ssl-ccc-mode.md ftp-ssl-ccc.md ftp-ssl-control.md get.md globoff.md happy-eyeballs-timeout-ms.md haproxy-clientip.md haproxy-protocol.md head.md header.md help.md hostpubmd5.md hostpubsha256.md hsts.md http0.9.md http1.0.md http1.1.md http2-prior-knowledge.md http2.md http3-only.md http3.md ignore-content-length.md insecure.md interface.md ip-tos.md ipfs-gateway.md ipv4.md ipv6.md json.md junk-session-cookies.md keepalive-cnt.md keepalive-time.md key-type.md key.md knownhosts.md krb.md libcurl.md limit-rate.md list-only.md local-port.md location-trusted.md location.md login-options.md mail-auth.md mail-from.md mail-rcpt-allowfails.md mail-rcpt.md mainpage.idx manual.md max-filesize.md max-redirs.md max-time.md metalink.md mptcp.md negotiate.md netrc-file.md netrc-optional.md netrc.md next.md no-alpn.md no-buffer.md no-clobber.md no-keepalive.md no-npn.md no-progress-meter.md no-sessionid.md noproxy.md ntlm-wb.md ntlm.md oauth2-bearer.md out-null.md output-dir.md output.md parallel-immediate.md parallel-max-host.md parallel-max.md parallel.md pass.md path-as-is.md pinnedpubkey.md post301.md post302.md post303.md preproxy.md progress-bar.md proto-default.md proto-redir.md proto.md proxy-anyauth.md proxy-basic.md proxy-ca-native.md proxy-cacert.md proxy-capath.md proxy-cert-type.md proxy-cert.md proxy-ciphers.md proxy-crlfile.md proxy-digest.md proxy-header.md proxy-http2.md proxy-insecure.md proxy-key-type.md proxy-key.md proxy-negotiate.md proxy-ntlm.md proxy-pass.md proxy-pinnedpubkey.md proxy-service-name.md proxy-ssl-allow-beast.md proxy-ssl-auto-client-cert.md proxy-tls13-ciphers.md proxy-tlsauthtype.md proxy-tlspassword.md proxy-tlsuser.md proxy-tlsv1.md proxy-user.md proxy.md proxy1.0.md proxytunnel.md pubkey.md quote.md random-file.md range.md rate.md raw.md referer.md remote-header-name.md remote-name-all.md remote-name.md remote-time.md remove-on-error.md request-target.md request.md resolve.md retry-all-errors.md retry-connrefused.md retry-delay.md retry-max-time.md retry.md sasl-authzid.md sasl-ir.md service-name.md show-error.md show-headers.md sigalgs.md silent.md skip-existing.md socks4.md socks4a.md socks5-basic.md socks5-gssapi-nec.md socks5-gssapi-service.md socks5-gssapi.md socks5-hostname.md socks5.md speed-limit.md speed-time.md ssl-allow-beast.md ssl-auto-client-cert.md ssl-no-revoke.md ssl-reqd.md ssl-revoke-best-effort.md ssl-sessions.md ssl.md sslv2.md sslv3.md stderr.md styled-output.md suppress-connect-headers.md tcp-fastopen.md tcp-nodelay.md telnet-option.md tftp-blksize.md tftp-no-options.md time-cond.md tls-earlydata.md tls-max.md tls13-ciphers.md tlsauthtype.md tlspassword.md tlsuser.md tlsv1.0.md tlsv1.1.md tlsv1.2.md tlsv1.3.md tlsv1.md tr-encoding.md trace-ascii.md trace-config.md trace-ids.md trace-time.md trace.md unix-socket.md upload-file.md upload-flags.md url-query.md url.md use-ascii.md user-agent.md user.md variable.md verbose.md version.md vlan-priority.md write-out.md xattr.mdexamples
.checksrc .gitignore 10-at-a-time.c CMakeLists.txt Makefile.am Makefile.example Makefile.inc README.md adddocsref.pl address-scope.c altsvc.c anyauthput.c block_ip.c cacertinmem.c certinfo.c chkspeed.c connect-to.c cookie_interface.c crawler.c debug.c default-scheme.c ephiperfifo.c evhiperfifo.c externalsocket.c fileupload.c ftp-delete.c ftp-wildcard.c ftpget.c ftpgetinfo.c ftpgetresp.c ftpsget.c ftpupload.c ftpuploadfrommem.c ftpuploadresume.c getinfo.c getinmemory.c getredirect.c getreferrer.c ghiper.c headerapi.c hiperfifo.c hsts-preload.c htmltidy.c htmltitle.cpp http-options.c http-post.c http2-download.c http2-pushinmemory.c http2-serverpush.c http2-upload.c http3-present.c http3.c httpcustomheader.c httpput-postfields.c httpput.c https.c imap-append.c imap-authzid.c imap-copy.c imap-create.c imap-delete.c imap-examine.c imap-fetch.c imap-list.c imap-lsub.c imap-multi.c imap-noop.c imap-search.c imap-ssl.c imap-store.c imap-tls.c interface.c ipv6.c keepalive.c localport.c log_failed_transfers.c maxconnects.c multi-app.c multi-debugcallback.c multi-double.c multi-event.c multi-formadd.c multi-legacy.c multi-post.c multi-single.c multi-uv.c netrc.c parseurl.c persistent.c pop3-authzid.c pop3-dele.c pop3-list.c pop3-multi.c pop3-noop.c pop3-retr.c pop3-ssl.c pop3-stat.c pop3-tls.c pop3-top.c pop3-uidl.c post-callback.c postinmemory.c postit2-formadd.c postit2.c progressfunc.c protofeats.c range.c resolve.c rtsp-options.c sendrecv.c sepheaders.c sessioninfo.c sftpget.c sftpuploadresume.c shared-connection-cache.c simple.c simplepost.c simplessl.c smooth-gtk-thread.c smtp-authzid.c smtp-expn.c smtp-mail.c smtp-mime.c smtp-multi.c smtp-ssl.c smtp-tls.c smtp-vrfy.c sslbackend.c synctime.c threaded.c unixsocket.c url2file.c urlapi.c usercertinmem.c version-check.pl websocket-cb.c websocket-updown.c websocket.c xmlstream.cinternals
BUFQ.md BUFREF.md CHECKSRC.md CLIENT-READERS.md CLIENT-WRITERS.md CODE_STYLE.md CONNECTION-FILTERS.md CREDENTIALS.md CURLX.md DYNBUF.md HASH.md LLIST.md MID.md MQTT.md MULTI-EV.md NEW-PROTOCOL.md PEERS.md PORTING.md RATELIMITS.md README.md SCORECARD.md SPLAY.md STRPARSE.md THRDPOOL-AND-QUEUE.md TIME-KEEPING.md TLS-SESSIONS.md UINT_SETS.md WEBSOCKET.mdlibcurl
opts
CMakeLists.txt CURLINFO_ACTIVESOCKET.md CURLINFO_APPCONNECT_TIME.md CURLINFO_APPCONNECT_TIME_T.md CURLINFO_CAINFO.md CURLINFO_CAPATH.md CURLINFO_CERTINFO.md CURLINFO_CONDITION_UNMET.md CURLINFO_CONNECT_TIME.md CURLINFO_CONNECT_TIME_T.md CURLINFO_CONN_ID.md CURLINFO_CONTENT_LENGTH_DOWNLOAD.md CURLINFO_CONTENT_LENGTH_DOWNLOAD_T.md CURLINFO_CONTENT_LENGTH_UPLOAD.md CURLINFO_CONTENT_LENGTH_UPLOAD_T.md CURLINFO_CONTENT_TYPE.md CURLINFO_COOKIELIST.md CURLINFO_EARLYDATA_SENT_T.md CURLINFO_EFFECTIVE_METHOD.md CURLINFO_EFFECTIVE_URL.md CURLINFO_FILETIME.md CURLINFO_FILETIME_T.md CURLINFO_FTP_ENTRY_PATH.md CURLINFO_HEADER_SIZE.md CURLINFO_HTTPAUTH_AVAIL.md CURLINFO_HTTPAUTH_USED.md CURLINFO_HTTP_CONNECTCODE.md CURLINFO_HTTP_VERSION.md CURLINFO_LASTSOCKET.md CURLINFO_LOCAL_IP.md CURLINFO_LOCAL_PORT.md CURLINFO_NAMELOOKUP_TIME.md CURLINFO_NAMELOOKUP_TIME_T.md CURLINFO_NUM_CONNECTS.md CURLINFO_OS_ERRNO.md CURLINFO_POSTTRANSFER_TIME_T.md CURLINFO_PRETRANSFER_TIME.md CURLINFO_PRETRANSFER_TIME_T.md CURLINFO_PRIMARY_IP.md CURLINFO_PRIMARY_PORT.md CURLINFO_PRIVATE.md CURLINFO_PROTOCOL.md CURLINFO_PROXYAUTH_AVAIL.md CURLINFO_PROXYAUTH_USED.md CURLINFO_PROXY_ERROR.md CURLINFO_PROXY_SSL_VERIFYRESULT.md CURLINFO_QUEUE_TIME_T.md CURLINFO_REDIRECT_COUNT.md CURLINFO_REDIRECT_TIME.md CURLINFO_REDIRECT_TIME_T.md CURLINFO_REDIRECT_URL.md CURLINFO_REFERER.md CURLINFO_REQUEST_SIZE.md CURLINFO_RESPONSE_CODE.md CURLINFO_RETRY_AFTER.md CURLINFO_RTSP_CLIENT_CSEQ.md CURLINFO_RTSP_CSEQ_RECV.md CURLINFO_RTSP_SERVER_CSEQ.md CURLINFO_RTSP_SESSION_ID.md CURLINFO_SCHEME.md CURLINFO_SIZE_DELIVERED.md CURLINFO_SIZE_DOWNLOAD.md CURLINFO_SIZE_DOWNLOAD_T.md CURLINFO_SIZE_UPLOAD.md CURLINFO_SIZE_UPLOAD_T.md CURLINFO_SPEED_DOWNLOAD.md CURLINFO_SPEED_DOWNLOAD_T.md CURLINFO_SPEED_UPLOAD.md CURLINFO_SPEED_UPLOAD_T.md CURLINFO_SSL_ENGINES.md CURLINFO_SSL_VERIFYRESULT.md CURLINFO_STARTTRANSFER_TIME.md CURLINFO_STARTTRANSFER_TIME_T.md CURLINFO_TLS_SESSION.md CURLINFO_TLS_SSL_PTR.md CURLINFO_TOTAL_TIME.md CURLINFO_TOTAL_TIME_T.md CURLINFO_USED_PROXY.md CURLINFO_XFER_ID.md CURLMINFO_XFERS_ADDED.md CURLMINFO_XFERS_CURRENT.md CURLMINFO_XFERS_DONE.md CURLMINFO_XFERS_PENDING.md CURLMINFO_XFERS_RUNNING.md CURLMOPT_CHUNK_LENGTH_PENALTY_SIZE.md CURLMOPT_CONTENT_LENGTH_PENALTY_SIZE.md CURLMOPT_MAXCONNECTS.md CURLMOPT_MAX_CONCURRENT_STREAMS.md CURLMOPT_MAX_HOST_CONNECTIONS.md CURLMOPT_MAX_PIPELINE_LENGTH.md CURLMOPT_MAX_TOTAL_CONNECTIONS.md CURLMOPT_NETWORK_CHANGED.md CURLMOPT_NOTIFYDATA.md CURLMOPT_NOTIFYFUNCTION.md CURLMOPT_PIPELINING.md CURLMOPT_PIPELINING_SERVER_BL.md CURLMOPT_PIPELINING_SITE_BL.md CURLMOPT_PUSHDATA.md CURLMOPT_PUSHFUNCTION.md CURLMOPT_QUICK_EXIT.md CURLMOPT_RESOLVE_THREADS_MAX.md CURLMOPT_SOCKETDATA.md CURLMOPT_SOCKETFUNCTION.md CURLMOPT_TIMERDATA.md CURLMOPT_TIMERFUNCTION.md CURLOPT_ABSTRACT_UNIX_SOCKET.md CURLOPT_ACCEPTTIMEOUT_MS.md CURLOPT_ACCEPT_ENCODING.md CURLOPT_ADDRESS_SCOPE.md CURLOPT_ALTSVC.md CURLOPT_ALTSVC_CTRL.md CURLOPT_APPEND.md CURLOPT_AUTOREFERER.md CURLOPT_AWS_SIGV4.md CURLOPT_BUFFERSIZE.md CURLOPT_CAINFO.md CURLOPT_CAINFO_BLOB.md CURLOPT_CAPATH.md CURLOPT_CA_CACHE_TIMEOUT.md CURLOPT_CERTINFO.md CURLOPT_CHUNK_BGN_FUNCTION.md CURLOPT_CHUNK_DATA.md CURLOPT_CHUNK_END_FUNCTION.md CURLOPT_CLOSESOCKETDATA.md CURLOPT_CLOSESOCKETFUNCTION.md CURLOPT_CONNECTTIMEOUT.md CURLOPT_CONNECTTIMEOUT_MS.md CURLOPT_CONNECT_ONLY.md CURLOPT_CONNECT_TO.md CURLOPT_CONV_FROM_NETWORK_FUNCTION.md CURLOPT_CONV_FROM_UTF8_FUNCTION.md CURLOPT_CONV_TO_NETWORK_FUNCTION.md CURLOPT_COOKIE.md CURLOPT_COOKIEFILE.md CURLOPT_COOKIEJAR.md CURLOPT_COOKIELIST.md CURLOPT_COOKIESESSION.md CURLOPT_COPYPOSTFIELDS.md CURLOPT_CRLF.md CURLOPT_CRLFILE.md CURLOPT_CURLU.md CURLOPT_CUSTOMREQUEST.md CURLOPT_DEBUGDATA.md CURLOPT_DEBUGFUNCTION.md CURLOPT_DEFAULT_PROTOCOL.md CURLOPT_DIRLISTONLY.md CURLOPT_DISALLOW_USERNAME_IN_URL.md CURLOPT_DNS_CACHE_TIMEOUT.md CURLOPT_DNS_INTERFACE.md CURLOPT_DNS_LOCAL_IP4.md CURLOPT_DNS_LOCAL_IP6.md CURLOPT_DNS_SERVERS.md CURLOPT_DNS_SHUFFLE_ADDRESSES.md CURLOPT_DNS_USE_GLOBAL_CACHE.md CURLOPT_DOH_SSL_VERIFYHOST.md CURLOPT_DOH_SSL_VERIFYPEER.md CURLOPT_DOH_SSL_VERIFYSTATUS.md CURLOPT_DOH_URL.md CURLOPT_ECH.md CURLOPT_EGDSOCKET.md CURLOPT_ERRORBUFFER.md CURLOPT_EXPECT_100_TIMEOUT_MS.md CURLOPT_FAILONERROR.md CURLOPT_FILETIME.md CURLOPT_FNMATCH_DATA.md CURLOPT_FNMATCH_FUNCTION.md CURLOPT_FOLLOWLOCATION.md CURLOPT_FORBID_REUSE.md CURLOPT_FRESH_CONNECT.md CURLOPT_FTPPORT.md CURLOPT_FTPSSLAUTH.md CURLOPT_FTP_ACCOUNT.md CURLOPT_FTP_ALTERNATIVE_TO_USER.md CURLOPT_FTP_CREATE_MISSING_DIRS.md CURLOPT_FTP_FILEMETHOD.md CURLOPT_FTP_SKIP_PASV_IP.md CURLOPT_FTP_SSL_CCC.md CURLOPT_FTP_USE_EPRT.md CURLOPT_FTP_USE_EPSV.md CURLOPT_FTP_USE_PRET.md CURLOPT_GSSAPI_DELEGATION.md CURLOPT_HAPPY_EYEBALLS_TIMEOUT_MS.md CURLOPT_HAPROXYPROTOCOL.md CURLOPT_HAPROXY_CLIENT_IP.md CURLOPT_HEADER.md CURLOPT_HEADERDATA.md CURLOPT_HEADERFUNCTION.md CURLOPT_HEADEROPT.md CURLOPT_HSTS.md CURLOPT_HSTSREADDATA.md CURLOPT_HSTSREADFUNCTION.md CURLOPT_HSTSWRITEDATA.md CURLOPT_HSTSWRITEFUNCTION.md CURLOPT_HSTS_CTRL.md CURLOPT_HTTP09_ALLOWED.md CURLOPT_HTTP200ALIASES.md CURLOPT_HTTPAUTH.md CURLOPT_HTTPGET.md CURLOPT_HTTPHEADER.md CURLOPT_HTTPPOST.md CURLOPT_HTTPPROXYTUNNEL.md CURLOPT_HTTP_CONTENT_DECODING.md CURLOPT_HTTP_TRANSFER_DECODING.md CURLOPT_HTTP_VERSION.md CURLOPT_IGNORE_CONTENT_LENGTH.md CURLOPT_INFILESIZE.md CURLOPT_INFILESIZE_LARGE.md CURLOPT_INTERFACE.md CURLOPT_INTERLEAVEDATA.md CURLOPT_INTERLEAVEFUNCTION.md CURLOPT_IOCTLDATA.md CURLOPT_IOCTLFUNCTION.md CURLOPT_IPRESOLVE.md CURLOPT_ISSUERCERT.md CURLOPT_ISSUERCERT_BLOB.md CURLOPT_KEEP_SENDING_ON_ERROR.md CURLOPT_KEYPASSWD.md CURLOPT_KRBLEVEL.md CURLOPT_LOCALPORT.md CURLOPT_LOCALPORTRANGE.md CURLOPT_LOGIN_OPTIONS.md CURLOPT_LOW_SPEED_LIMIT.md CURLOPT_LOW_SPEED_TIME.md CURLOPT_MAIL_AUTH.md CURLOPT_MAIL_FROM.md CURLOPT_MAIL_RCPT.md CURLOPT_MAIL_RCPT_ALLOWFAILS.md CURLOPT_MAXAGE_CONN.md CURLOPT_MAXCONNECTS.md CURLOPT_MAXFILESIZE.md CURLOPT_MAXFILESIZE_LARGE.md CURLOPT_MAXLIFETIME_CONN.md CURLOPT_MAXREDIRS.md CURLOPT_MAX_RECV_SPEED_LARGE.md CURLOPT_MAX_SEND_SPEED_LARGE.md CURLOPT_MIMEPOST.md CURLOPT_MIME_OPTIONS.md CURLOPT_NETRC.md CURLOPT_NETRC_FILE.md CURLOPT_NEW_DIRECTORY_PERMS.md CURLOPT_NEW_FILE_PERMS.md CURLOPT_NOBODY.md CURLOPT_NOPROGRESS.md CURLOPT_NOPROXY.md CURLOPT_NOSIGNAL.md CURLOPT_OPENSOCKETDATA.md CURLOPT_OPENSOCKETFUNCTION.md CURLOPT_PASSWORD.md CURLOPT_PATH_AS_IS.md CURLOPT_PINNEDPUBLICKEY.md CURLOPT_PIPEWAIT.md CURLOPT_PORT.md CURLOPT_POST.md CURLOPT_POSTFIELDS.md CURLOPT_POSTFIELDSIZE.md CURLOPT_POSTFIELDSIZE_LARGE.md CURLOPT_POSTQUOTE.md CURLOPT_POSTREDIR.md CURLOPT_PREQUOTE.md CURLOPT_PREREQDATA.md CURLOPT_PREREQFUNCTION.md CURLOPT_PRE_PROXY.md CURLOPT_PRIVATE.md CURLOPT_PROGRESSDATA.md CURLOPT_PROGRESSFUNCTION.md CURLOPT_PROTOCOLS.md CURLOPT_PROTOCOLS_STR.md CURLOPT_PROXY.md CURLOPT_PROXYAUTH.md CURLOPT_PROXYHEADER.md CURLOPT_PROXYPASSWORD.md CURLOPT_PROXYPORT.md CURLOPT_PROXYTYPE.md CURLOPT_PROXYUSERNAME.md CURLOPT_PROXYUSERPWD.md CURLOPT_PROXY_CAINFO.md CURLOPT_PROXY_CAINFO_BLOB.md CURLOPT_PROXY_CAPATH.md CURLOPT_PROXY_CRLFILE.md CURLOPT_PROXY_ISSUERCERT.md CURLOPT_PROXY_ISSUERCERT_BLOB.md CURLOPT_PROXY_KEYPASSWD.md CURLOPT_PROXY_PINNEDPUBLICKEY.md CURLOPT_PROXY_SERVICE_NAME.md CURLOPT_PROXY_SSLCERT.md CURLOPT_PROXY_SSLCERTTYPE.md CURLOPT_PROXY_SSLCERT_BLOB.md CURLOPT_PROXY_SSLKEY.md CURLOPT_PROXY_SSLKEYTYPE.md CURLOPT_PROXY_SSLKEY_BLOB.md CURLOPT_PROXY_SSLVERSION.md CURLOPT_PROXY_SSL_CIPHER_LIST.md CURLOPT_PROXY_SSL_OPTIONS.md CURLOPT_PROXY_SSL_VERIFYHOST.md CURLOPT_PROXY_SSL_VERIFYPEER.md CURLOPT_PROXY_TLS13_CIPHERS.md CURLOPT_PROXY_TLSAUTH_PASSWORD.md CURLOPT_PROXY_TLSAUTH_TYPE.md CURLOPT_PROXY_TLSAUTH_USERNAME.md CURLOPT_PROXY_TRANSFER_MODE.md CURLOPT_PUT.md CURLOPT_QUICK_EXIT.md CURLOPT_QUOTE.md CURLOPT_RANDOM_FILE.md CURLOPT_RANGE.md CURLOPT_READDATA.md CURLOPT_READFUNCTION.md CURLOPT_REDIR_PROTOCOLS.md CURLOPT_REDIR_PROTOCOLS_STR.md CURLOPT_REFERER.md CURLOPT_REQUEST_TARGET.md CURLOPT_RESOLVE.md CURLOPT_RESOLVER_START_DATA.md CURLOPT_RESOLVER_START_FUNCTION.md CURLOPT_RESUME_FROM.md CURLOPT_RESUME_FROM_LARGE.md CURLOPT_RTSP_CLIENT_CSEQ.md CURLOPT_RTSP_REQUEST.md CURLOPT_RTSP_SERVER_CSEQ.md CURLOPT_RTSP_SESSION_ID.md CURLOPT_RTSP_STREAM_URI.md CURLOPT_RTSP_TRANSPORT.md CURLOPT_SASL_AUTHZID.md CURLOPT_SASL_IR.md CURLOPT_SEEKDATA.md CURLOPT_SEEKFUNCTION.md CURLOPT_SERVER_RESPONSE_TIMEOUT.md CURLOPT_SERVER_RESPONSE_TIMEOUT_MS.md CURLOPT_SERVICE_NAME.md CURLOPT_SHARE.md CURLOPT_SOCKOPTDATA.md CURLOPT_SOCKOPTFUNCTION.md CURLOPT_SOCKS5_AUTH.md CURLOPT_SOCKS5_GSSAPI_NEC.md CURLOPT_SOCKS5_GSSAPI_SERVICE.md CURLOPT_SSH_AUTH_TYPES.md CURLOPT_SSH_COMPRESSION.md CURLOPT_SSH_HOSTKEYDATA.md CURLOPT_SSH_HOSTKEYFUNCTION.md CURLOPT_SSH_HOST_PUBLIC_KEY_MD5.md CURLOPT_SSH_HOST_PUBLIC_KEY_SHA256.md CURLOPT_SSH_KEYDATA.md CURLOPT_SSH_KEYFUNCTION.md CURLOPT_SSH_KNOWNHOSTS.md CURLOPT_SSH_PRIVATE_KEYFILE.md CURLOPT_SSH_PUBLIC_KEYFILE.md CURLOPT_SSLCERT.md CURLOPT_SSLCERTTYPE.md CURLOPT_SSLCERT_BLOB.md CURLOPT_SSLENGINE.md CURLOPT_SSLENGINE_DEFAULT.md CURLOPT_SSLKEY.md CURLOPT_SSLKEYTYPE.md CURLOPT_SSLKEY_BLOB.md CURLOPT_SSLVERSION.md CURLOPT_SSL_CIPHER_LIST.md CURLOPT_SSL_CTX_DATA.md CURLOPT_SSL_CTX_FUNCTION.md CURLOPT_SSL_EC_CURVES.md CURLOPT_SSL_ENABLE_ALPN.md CURLOPT_SSL_ENABLE_NPN.md CURLOPT_SSL_FALSESTART.md CURLOPT_SSL_OPTIONS.md CURLOPT_SSL_SESSIONID_CACHE.md CURLOPT_SSL_SIGNATURE_ALGORITHMS.md CURLOPT_SSL_VERIFYHOST.md CURLOPT_SSL_VERIFYPEER.md CURLOPT_SSL_VERIFYSTATUS.md CURLOPT_STDERR.md CURLOPT_STREAM_DEPENDS.md CURLOPT_STREAM_DEPENDS_E.md CURLOPT_STREAM_WEIGHT.md CURLOPT_SUPPRESS_CONNECT_HEADERS.md CURLOPT_TCP_FASTOPEN.md CURLOPT_TCP_KEEPALIVE.md CURLOPT_TCP_KEEPCNT.md CURLOPT_TCP_KEEPIDLE.md CURLOPT_TCP_KEEPINTVL.md CURLOPT_TCP_NODELAY.md CURLOPT_TELNETOPTIONS.md CURLOPT_TFTP_BLKSIZE.md CURLOPT_TFTP_NO_OPTIONS.md CURLOPT_TIMECONDITION.md CURLOPT_TIMEOUT.md CURLOPT_TIMEOUT_MS.md CURLOPT_TIMEVALUE.md CURLOPT_TIMEVALUE_LARGE.md CURLOPT_TLS13_CIPHERS.md CURLOPT_TLSAUTH_PASSWORD.md CURLOPT_TLSAUTH_TYPE.md CURLOPT_TLSAUTH_USERNAME.md CURLOPT_TRAILERDATA.md CURLOPT_TRAILERFUNCTION.md CURLOPT_TRANSFERTEXT.md CURLOPT_TRANSFER_ENCODING.md CURLOPT_UNIX_SOCKET_PATH.md CURLOPT_UNRESTRICTED_AUTH.md CURLOPT_UPKEEP_INTERVAL_MS.md CURLOPT_UPLOAD.md CURLOPT_UPLOAD_BUFFERSIZE.md CURLOPT_UPLOAD_FLAGS.md CURLOPT_URL.md CURLOPT_USERAGENT.md CURLOPT_USERNAME.md CURLOPT_USERPWD.md CURLOPT_USE_SSL.md CURLOPT_VERBOSE.md CURLOPT_WILDCARDMATCH.md CURLOPT_WRITEDATA.md CURLOPT_WRITEFUNCTION.md CURLOPT_WS_OPTIONS.md CURLOPT_XFERINFODATA.md CURLOPT_XFERINFOFUNCTION.md CURLOPT_XOAUTH2_BEARER.md CURLSHOPT_LOCKFUNC.md CURLSHOPT_SHARE.md CURLSHOPT_UNLOCKFUNC.md CURLSHOPT_UNSHARE.md CURLSHOPT_USERDATA.md Makefile.am Makefile.incinclude
curl
Makefile.am curl.h curlver.h easy.h header.h mprintf.h multi.h options.h stdcheaders.h system.h typecheck-gcc.h urlapi.h websockets.hlib
curlx
base64.c base64.h basename.c basename.h dynbuf.c dynbuf.h fopen.c fopen.h inet_ntop.c inet_ntop.h inet_pton.c inet_pton.h multibyte.c multibyte.h nonblock.c nonblock.h snprintf.c snprintf.h strcopy.c strcopy.h strdup.c strdup.h strerr.c strerr.h strparse.c strparse.h timediff.c timediff.h timeval.c timeval.h version_win32.c version_win32.h wait.c wait.h warnless.c warnless.h winapi.c winapi.hvauth
cleartext.c cram.c digest.c digest.h digest_sspi.c gsasl.c krb5_gssapi.c krb5_sspi.c ntlm.c ntlm_sspi.c oauth2.c spnego_gssapi.c spnego_sspi.c vauth.c vauth.hvquic
curl_ngtcp2.c curl_ngtcp2.h curl_quiche.c curl_quiche.h vquic-tls.c vquic-tls.h vquic.c vquic.h vquic_int.hvtls
apple.c apple.h cipher_suite.c cipher_suite.h gtls.c gtls.h hostcheck.c hostcheck.h keylog.c keylog.h mbedtls.c mbedtls.h openssl.c openssl.h rustls.c rustls.h schannel.c schannel.h schannel_int.h schannel_verify.c vtls.c vtls.h vtls_int.h vtls_scache.c vtls_scache.h vtls_spack.c vtls_spack.h wolfssl.c wolfssl.h x509asn1.c x509asn1.hm4
.gitignore curl-amissl.m4 curl-apple-sectrust.m4 curl-compilers.m4 curl-confopts.m4 curl-functions.m4 curl-gnutls.m4 curl-mbedtls.m4 curl-openssl.m4 curl-override.m4 curl-reentrant.m4 curl-rustls.m4 curl-schannel.m4 curl-sysconfig.m4 curl-wolfssl.m4 xc-am-iface.m4 xc-cc-check.m4 xc-lt-iface.m4 xc-val-flgs.m4 zz40-xc-ovr.m4 zz50-xc-ovr.m4projects
OS400
.checksrc README.OS400 ccsidcurl.c ccsidcurl.h config400.default curl.cmd curl.inc.in curlcl.c curlmain.c initscript.sh make-docs.sh make-include.sh make-lib.sh make-src.sh make-tests.sh makefile.sh os400sys.c os400sys.hWindows
tmpl
.gitattributes README.txt curl-all.sln curl.sln curl.vcxproj curl.vcxproj.filters libcurl.sln libcurl.vcxproj libcurl.vcxproj.filtersvms
Makefile.am backup_gnv_curl_src.com build_curl-config_script.com build_gnv_curl.com build_gnv_curl_pcsi_desc.com build_gnv_curl_pcsi_text.com build_gnv_curl_release_notes.com build_libcurl_pc.com build_vms.com clean_gnv_curl.com compare_curl_source.com config_h.com curl_crtl_init.c curl_gnv_build_steps.txt curl_release_note_start.txt curl_startup.com curlmsg.h curlmsg.msg curlmsg.sdl curlmsg_vms.h generate_config_vms_h_curl.com generate_vax_transfer.com gnv_conftest.c_first gnv_curl_configure.sh gnv_libcurl_symbols.opt gnv_link_curl.com macro32_exactcase.patch make_gnv_curl_install.sh make_pcsi_curl_kit_name.com pcsi_gnv_curl_file_list.txt pcsi_product_gnv_curl.com readme report_openssl_version.c setup_gnv_curl_build.com stage_curl_install.com vms_eco_level.hscripts
.checksrc CMakeLists.txt Makefile.am badwords badwords-all badwords.txt cd2cd cd2nroff cdall checksrc-all.pl checksrc.pl cmakelint.sh completion.pl contributors.sh contrithanks.sh coverage.sh delta dmaketgz extract-unit-protos firefox-db2pem.sh installcheck.sh maketgz managen mdlinkcheck mk-ca-bundle.pl mk-unity.pl nroff2cd perlcheck.sh pythonlint.sh randdisable release-notes.pl release-tools.sh schemetable.c singleuse.pl spacecheck.pl top-complexity top-length verify-release wcurlsrc
.checksrc .gitignore CMakeLists.txt Makefile.am Makefile.inc config2setopts.c config2setopts.h curl.rc curlinfo.c mk-file-embed.pl mkhelp.pl slist_wc.c slist_wc.h terminal.c terminal.h tool_cb_dbg.c tool_cb_dbg.h tool_cb_hdr.c tool_cb_hdr.h tool_cb_prg.c tool_cb_prg.h tool_cb_rea.c tool_cb_rea.h tool_cb_see.c tool_cb_see.h tool_cb_soc.c tool_cb_soc.h tool_cb_wrt.c tool_cb_wrt.h tool_cfgable.c tool_cfgable.h tool_dirhie.c tool_dirhie.h tool_doswin.c tool_doswin.h tool_easysrc.c tool_easysrc.h tool_filetime.c tool_filetime.h tool_findfile.c tool_findfile.h tool_formparse.c tool_formparse.h tool_getparam.c tool_getparam.h tool_getpass.c tool_getpass.h tool_help.c tool_help.h tool_helpers.c tool_helpers.h tool_hugehelp.h tool_ipfs.c tool_ipfs.h tool_libinfo.c tool_libinfo.h tool_listhelp.c tool_main.c tool_main.h tool_msgs.c tool_msgs.h tool_operate.c tool_operate.h tool_operhlp.c tool_operhlp.h tool_paramhlp.c tool_paramhlp.h tool_parsecfg.c tool_parsecfg.h tool_progress.c tool_progress.h tool_sdecls.h tool_setopt.c tool_setopt.h tool_setup.h tool_ssls.c tool_ssls.h tool_stderr.c tool_stderr.h tool_urlglob.c tool_urlglob.h tool_util.c tool_util.h tool_version.h tool_vms.c tool_vms.h tool_writeout.c tool_writeout.h tool_writeout_json.c tool_writeout_json.h tool_xattr.c tool_xattr.h var.c var.htests
certs
.gitignore CMakeLists.txt Makefile.am Makefile.inc genserv.pl srp-verifier-conf srp-verifier-db test-ca.cnf test-ca.prm test-client-cert.prm test-client-eku-only.prm test-localhost-san-first.prm test-localhost-san-last.prm test-localhost.nn.prm test-localhost.prm test-localhost0h.prmdata
.gitignore DISABLED Makefile.am data-xml1 data1400.c data1401.c data1402.c data1403.c data1404.c data1405.c data1406.c data1407.c data1420.c data1461.txt data1463.txt data1465.c data1481.c data1705-1.md data1705-2.md data1705-3.md data1705-4.md data1705-stdout.1 data1706-1.md data1706-2.md data1706-3.md data1706-4.md data1706-stdout.txt data320.html test1 test10 test100 test1000 test1001 test1002 test1003 test1004 test1005 test1006 test1007 test1008 test1009 test101 test1010 test1011 test1012 test1013 test1014 test1015 test1016 test1017 test1018 test1019 test102 test1020 test1021 test1022 test1023 test1024 test1025 test1026 test1027 test1028 test1029 test103 test1030 test1031 test1032 test1033 test1034 test1035 test1036 test1037 test1038 test1039 test104 test1040 test1041 test1042 test1043 test1044 test1045 test1046 test1047 test1048 test1049 test105 test1050 test1051 test1052 test1053 test1054 test1055 test1056 test1057 test1058 test1059 test106 test1060 test1061 test1062 test1063 test1064 test1065 test1066 test1067 test1068 test1069 test107 test1070 test1071 test1072 test1073 test1074 test1075 test1076 test1077 test1078 test1079 test108 test1080 test1081 test1082 test1083 test1084 test1085 test1086 test1087 test1088 test1089 test109 test1090 test1091 test1092 test1093 test1094 test1095 test1096 test1097 test1098 test1099 test11 test110 test1100 test1101 test1102 test1103 test1104 test1105 test1106 test1107 test1108 test1109 test111 test1110 test1111 test1112 test1113 test1114 test1115 test1116 test1117 test1118 test1119 test112 test1120 test1121 test1122 test1123 test1124 test1125 test1126 test1127 test1128 test1129 test113 test1130 test1131 test1132 test1133 test1134 test1135 test1136 test1137 test1138 test1139 test114 test1140 test1141 test1142 test1143 test1144 test1145 test1146 test1147 test1148 test1149 test115 test1150 test1151 test1152 test1153 test1154 test1155 test1156 test1157 test1158 test1159 test116 test1160 test1161 test1162 test1163 test1164 test1165 test1166 test1167 test1168 test1169 test117 test1170 test1171 test1172 test1173 test1174 test1175 test1176 test1177 test1178 test1179 test118 test1180 test1181 test1182 test1183 test1184 test1185 test1186 test1187 test1188 test1189 test119 test1190 test1191 test1192 test1193 test1194 test1195 test1196 test1197 test1198 test1199 test12 test120 test1200 test1201 test1202 test1203 test1204 test1205 test1206 test1207 test1208 test1209 test121 test1210 test1211 test1212 test1213 test1214 test1215 test1216 test1217 test1218 test1219 test122 test1220 test1221 test1222 test1223 test1224 test1225 test1226 test1227 test1228 test1229 test123 test1230 test1231 test1232 test1233 test1234 test1235 test1236 test1237 test1238 test1239 test124 test1240 test1241 test1242 test1243 test1244 test1245 test1246 test1247 test1248 test1249 test125 test1250 test1251 test1252 test1253 test1254 test1255 test1256 test1257 test1258 test1259 test126 test1260 test1261 test1262 test1263 test1264 test1265 test1266 test1267 test1268 test1269 test127 test1270 test1271 test1272 test1273 test1274 test1275 test1276 test1277 test1278 test1279 test128 test1280 test1281 test1282 test1283 test1284 test1285 test1286 test1287 test1288 test1289 test129 test1290 test1291 test1292 test1293 test1294 test1295 test1296 test1297 test1298 test1299 test13 test130 test1300 test1301 test1302 test1303 test1304 test1305 test1306 test1307 test1308 test1309 test131 test1310 test1311 test1312 test1313 test1314 test1315 test1316 test1317 test1318 test1319 test132 test1320 test1321 test1322 test1323 test1324 test1325 test1326 test1327 test1328 test1329 test133 test1330 test1331 test1332 test1333 test1334 test1335 test1336 test1337 test1338 test1339 test134 test1340 test1341 test1342 test1343 test1344 test1345 test1346 test1347 test1348 test1349 test135 test1350 test1351 test1352 test1353 test1354 test1355 test1356 test1357 test1358 test1359 test136 test1360 test1361 test1362 test1363 test1364 test1365 test1366 test1367 test1368 test1369 test137 test1370 test1371 test1372 test1373 test1374 test1375 test1376 test1377 test1378 test1379 test138 test1380 test1381 test1382 test1383 test1384 test1385 test1386 test1387 test1388 test1389 test139 test1390 test1391 test1392 test1393 test1394 test1395 test1396 test1397 test1398 test1399 test14 test140 test1400 test1401 test1402 test1403 test1404 test1405 test1406 test1407 test1408 test1409 test141 test1410 test1411 test1412 test1413 test1414 test1415 test1416 test1417 test1418 test1419 test142 test1420 test1421 test1422 test1423 test1424 test1425 test1426 test1427 test1428 test1429 test143 test1430 test1431 test1432 test1433 test1434 test1435 test1436 test1437 test1438 test1439 test144 test1440 test1441 test1442 test1443 test1444 test1445 test1446 test1447 test1448 test1449 test145 test1450 test1451 test1452 test1453 test1454 test1455 test1456 test1457 test1458 test1459 test146 test1460 test1461 test1462 test1463 test1464 test1465 test1466 test1467 test1468 test1469 test147 test1470 test1471 test1472 test1473 test1474 test1475 test1476 test1477 test1478 test1479 test148 test1480 test1481 test1482 test1483 test1484 test1485 test1486 test1487 test1488 test1489 test149 test1490 test1491 test1492 test1493 test1494 test1495 test1496 test1497 test1498 test1499 test15 test150 test1500 test1501 test1502 test1503 test1504 test1505 test1506 test1507 test1508 test1509 test151 test1510 test1511 test1512 test1513 test1514 test1515 test1516 test1517 test1518 test1519 test152 test1520 test1521 test1522 test1523 test1524 test1525 test1526 test1527 test1528 test1529 test153 test1530 test1531 test1532 test1533 test1534 test1535 test1536 test1537 test1538 test1539 test154 test1540 test1541 test1542 test1543 test1544 test1545 test1546 test1547 test1548 test1549 test155 test1550 test1551 test1552 test1553 test1554 test1555 test1556 test1557 test1558 test1559 test156 test1560 test1561 test1562 test1563 test1564 test1565 test1566 test1567 test1568 test1569 test157 test1570 test1571 test1572 test1573 test1574 test1575 test1576 test1577 test1578 test1579 test158 test1580 test1581 test1582 test1583 test1584 test1585 test1586 test1587 test1588 test1589 test159 test1590 test1591 test1592 test1593 test1594 test1595 test1596 test1597 test1598 test1599 test16 test160 test1600 test1601 test1602 test1603 test1604 test1605 test1606 test1607 test1608 test1609 test161 test1610 test1611 test1612 test1613 test1614 test1615 test1616 test1617 test1618 test1619 test162 test1620 test1621 test1622 test1623 test1624 test1625 test1626 test1627 test1628 test1629 test163 test1630 test1631 test1632 test1633 test1634 test1635 test1636 test1637 test1638 test1639 test164 test1640 test1641 test1642 test1643 test1644 test1645 test165 test1650 test1651 test1652 test1653 test1654 test1655 test1656 test1657 test1658 test1659 test166 test1660 test1661 test1662 test1663 test1664 test1665 test1666 test1667 test1668 test1669 test167 test1670 test1671 test1672 test1673 test1674 test1675 test1676 test168 test1680 test1681 test1682 test1683 test1684 test1685 test169 test17 test170 test1700 test1701 test1702 test1703 test1704 test1705 test1706 test1707 test1708 test1709 test171 test1710 test1711 test1712 test1713 test1714 test1715 test172 test1720 test1721 test173 test174 test175 test176 test177 test178 test179 test18 test180 test1800 test1801 test1802 test181 test182 test183 test184 test1847 test1848 test1849 test185 test1850 test1851 test186 test187 test188 test189 test19 test190 test1900 test1901 test1902 test1903 test1904 test1905 test1906 test1907 test1908 test1909 test191 test1910 test1911 test1912 test1913 test1914 test1915 test1916 test1917 test1918 test1919 test192 test1920 test1921 test193 test1933 test1934 test1935 test1936 test1937 test1938 test1939 test194 test1940 test1941 test1942 test1943 test1944 test1945 test1946 test1947 test1948 test195 test1955 test1956 test1957 test1958 test1959 test196 test1960 test1964 test1965 test1966 test197 test1970 test1971 test1972 test1973 test1974 test1975 test1976 test1977 test1978 test1979 test198 test1980 test1981 test1982 test1983 test1984 test199 test2 test20 test200 test2000 test2001 test2002 test2003 test2004 test2005 test2006 test2007 test2008 test2009 test201 test2010 test2011 test2012 test2013 test2014 test202 test2023 test2024 test2025 test2026 test2027 test2028 test2029 test203 test2030 test2031 test2032 test2033 test2034 test2035 test2037 test2038 test2039 test204 test2040 test2041 test2042 test2043 test2044 test2045 test2046 test2047 test2048 test2049 test205 test2050 test2051 test2052 test2053 test2054 test2055 test2056 test2057 test2058 test2059 test206 test2060 test2061 test2062 test2063 test2064 test2065 test2066 test2067 test2068 test2069 test207 test2070 test2071 test2072 test2073 test2074 test2075 test2076 test2077 test2078 test2079 test208 test2080 test2081 test2082 test2083 test2084 test2085 test2086 test2087 test2088 test2089 test209 test2090 test2091 test2092 test21 test210 test2100 test2101 test2102 test2103 test2104 test211 test212 test213 test214 test215 test216 test217 test218 test219 test22 test220 test2200 test2201 test2202 test2203 test2204 test2205 test2206 test2207 test221 test222 test223 test224 test225 test226 test227 test228 test229 test23 test230 test2300 test2301 test2302 test2303 test2304 test2306 test2307 test2308 test2309 test231 test232 test233 test234 test235 test236 test237 test238 test239 test24 test240 test2400 test2401 test2402 test2403 test2404 test2405 test2406 test2407 test2408 test2409 test241 test2410 test2411 test242 test243 test244 test245 test246 test247 test248 test249 test25 test250 test2500 test2501 test2502 test2503 test2504 test2505 test2506 test251 test252 test253 test254 test255 test256 test257 test258 test259 test26 test260 test2600 test2601 test2602 test2603 test2604 test2605 test261 test262 test263 test264 test265 test266 test267 test268 test269 test27 test270 test2700 test2701 test2702 test2703 test2704 test2705 test2706 test2707 test2708 test2709 test271 test2710 test2711 test2712 test2713 test2714 test2715 test2716 test2717 test2718 test2719 test272 test2720 test2721 test2722 test2723 test273 test274 test275 test276 test277 test278 test279 test28 test280 test281 test282 test283 test284 test285 test286 test287 test288 test289 test29 test290 test291 test292 test293 test294 test295 test296 test297 test298 test299 test3 test30 test300 test3000 test3001 test3002 test3003 test3004 test3005 test3006 test3007 test3008 test3009 test301 test3010 test3011 test3012 test3013 test3014 test3015 test3016 test3017 test3018 test3019 test302 test3020 test3021 test3022 test3023 test3024 test3025 test3026 test3027 test3028 test3029 test303 test3030 test3031 test3032 test3033 test3034 test3035 test3036 test304 test305 test306 test307 test308 test309 test31 test310 test3100 test3101 test3102 test3103 test3104 test3105 test3106 test311 test312 test313 test314 test315 test316 test317 test318 test319 test32 test320 test3200 test3201 test3202 test3203 test3204 test3205 test3206 test3207 test3208 test3209 test321 test3210 test3211 test3212 test3213 test3214 test3215 test3216 test3217 test3218 test3219 test322 test3220 test323 test324 test325 test326 test327 test328 test329 test33 test330 test3300 test3301 test3302 test331 test332 test333 test334 test335 test336 test337 test338 test339 test34 test340 test341 test342 test343 test344 test345 test346 test347 test348 test349 test35 test350 test351 test352 test353 test354 test355 test356 test357 test358 test359 test36 test360 test361 test362 test363 test364 test365 test366 test367 test368 test369 test37 test370 test371 test372 test373 test374 test375 test376 test378 test379 test38 test380 test381 test383 test384 test385 test386 test387 test388 test389 test39 test390 test391 test392 test393 test394 test395 test396 test397 test398 test399 test4 test40 test400 test4000 test4001 test401 test402 test403 test404 test405 test406 test407 test408 test409 test41 test410 test411 test412 test413 test414 test415 test416 test417 test418 test419 test42 test420 test421 test422 test423 test424 test425 test426 test427 test428 test429 test43 test430 test431 test432 test433 test434 test435 test436 test437 test438 test439 test44 test440 test441 test442 test443 test444 test445 test446 test447 test448 test449 test45 test450 test451 test452 test453 test454 test455 test456 test457 test458 test459 test46 test460 test461 test462 test463 test467 test468 test469 test47 test470 test471 test472 test473 test474 test475 test476 test477 test478 test479 test48 test480 test481 test482 test483 test484 test485 test486 test487 test488 test489 test49 test490 test491 test492 test493 test494 test495 test496 test497 test498 test499 test5 test50 test500 test501 test502 test503 test504 test505 test506 test507 test508 test509 test51 test510 test511 test512 test513 test514 test515 test516 test517 test518 test519 test52 test520 test521 test522 test523 test524 test525 test526 test527 test528 test529 test53 test530 test531 test532 test533 test534 test535 test536 test537 test538 test539 test54 test540 test541 test542 test543 test544 test545 test546 test547 test548 test549 test55 test550 test551 test552 test553 test554 test555 test556 test557 test558 test559 test56 test560 test561 test562 test563 test564 test565 test566 test567 test568 test569 test57 test570 test571 test572 test573 test574 test575 test576 test577 test578 test579 test58 test580 test581 test582 test583 test584 test585 test586 test587 test588 test589 test59 test590 test591 test592 test593 test594 test595 test596 test597 test598 test599 test6 test60 test600 test601 test602 test603 test604 test605 test606 test607 test608 test609 test61 test610 test611 test612 test613 test614 test615 test616 test617 test618 test619 test62 test620 test621 test622 test623 test624 test625 test626 test627 test628 test629 test63 test630 test631 test632 test633 test634 test635 test636 test637 test638 test639 test64 test640 test641 test642 test643 test644 test645 test646 test647 test648 test649 test65 test650 test651 test652 test653 test654 test655 test656 test658 test659 test66 test660 test661 test662 test663 test664 test665 test666 test667 test668 test669 test67 test670 test671 test672 test673 test674 test675 test676 test677 test678 test679 test68 test680 test681 test682 test683 test684 test685 test686 test687 test688 test689 test69 test690 test691 test692 test693 test694 test695 test696 test697 test698 test699 test7 test70 test700 test701 test702 test703 test704 test705 test706 test707 test708 test709 test71 test710 test711 test712 test713 test714 test715 test716 test717 test718 test719 test72 test720 test721 test722 test723 test724 test725 test726 test727 test728 test729 test73 test730 test731 test732 test733 test734 test735 test736 test737 test738 test739 test74 test740 test741 test742 test743 test744 test745 test746 test747 test748 test749 test75 test750 test751 test752 test753 test754 test755 test756 test757 test758 test759 test76 test760 test761 test762 test763 test764 test765 test766 test767 test768 test769 test77 test770 test771 test772 test773 test774 test775 test776 test777 test778 test779 test78 test780 test781 test782 test783 test784 test785 test786 test787 test788 test789 test79 test790 test791 test792 test793 test794 test795 test796 test797 test798 test799 test8 test80 test800 test801 test802 test803 test804 test805 test806 test807 test808 test809 test81 test810 test811 test812 test813 test814 test815 test816 test817 test818 test819 test82 test820 test821 test822 test823 test824 test825 test826 test827 test828 test829 test83 test830 test831 test832 test833 test834 test835 test836 test837 test838 test839 test84 test840 test841 test842 test843 test844 test845 test846 test847 test848 test849 test85 test850 test851 test852 test853 test854 test855 test856 test857 test858 test859 test86 test860 test861 test862 test863 test864 test865 test866 test867 test868 test869 test87 test870 test871 test872 test873 test874 test875 test876 test877 test878 test879 test88 test880 test881 test882 test883 test884 test885 test886 test887 test888 test889 test89 test890 test891 test892 test893 test894 test895 test896 test897 test898 test899 test9 test90 test900 test901 test902 test903 test904 test905 test906 test907 test908 test909 test91 test910 test911 test912 test913 test914 test915 test916 test917 test918 test919 test92 test920 test921 test922 test923 test924 test925 test926 test927 test928 test929 test93 test930 test931 test932 test933 test934 test935 test936 test937 test938 test939 test94 test940 test941 test942 test943 test944 test945 test946 test947 test948 test949 test95 test950 test951 test952 test953 test954 test955 test956 test957 test958 test959 test96 test960 test961 test962 test963 test964 test965 test966 test967 test968 test969 test97 test970 test971 test972 test973 test974 test975 test976 test977 test978 test979 test98 test980 test981 test982 test983 test984 test985 test986 test987 test988 test989 test99 test990 test991 test992 test993 test994 test995 test996 test997 test998 test999http
testenv
__init__.py caddy.py certs.py client.py curl.py dante.py dnsd.py env.py httpd.py nghttpx.py ports.py sshd.py vsftpd.py ws_echo_server.pylibtest
.gitignore CMakeLists.txt Makefile.am Makefile.inc cli_ftp_upload.c cli_h2_pausing.c cli_h2_serverpush.c cli_h2_upgrade_extreme.c cli_hx_download.c cli_hx_upload.c cli_tls_session_reuse.c cli_upload_pausing.c cli_ws_data.c cli_ws_pingpong.c first.c first.h lib1156.c lib1301.c lib1308.c lib1485.c lib1500.c lib1501.c lib1502.c lib1506.c lib1507.c lib1508.c lib1509.c lib1510.c lib1511.c lib1512.c lib1513.c lib1514.c lib1515.c lib1517.c lib1518.c lib1520.c lib1522.c lib1523.c lib1525.c lib1526.c lib1527.c lib1528.c lib1529.c lib1530.c lib1531.c lib1532.c lib1533.c lib1534.c lib1535.c lib1536.c lib1537.c lib1538.c lib1540.c lib1541.c lib1542.c lib1545.c lib1549.c lib1550.c lib1551.c lib1552.c lib1553.c lib1554.c lib1555.c lib1556.c lib1557.c lib1558.c lib1559.c lib1560.c lib1564.c lib1565.c lib1567.c lib1568.c lib1569.c lib1571.c lib1576.c lib1582.c lib1587.c lib1588.c lib1589.c lib1591.c lib1592.c lib1593.c lib1594.c lib1597.c lib1598.c lib1599.c lib1662.c lib1900.c lib1901.c lib1902.c lib1903.c lib1905.c lib1906.c lib1907.c lib1908.c lib1910.c lib1911.c lib1912.c lib1913.c lib1915.c lib1916.c lib1918.c lib1919.c lib1920.c lib1921.c lib1933.c lib1934.c lib1935.c lib1936.c lib1937.c lib1938.c lib1939.c lib1940.c lib1945.c lib1947.c lib1948.c lib1955.c lib1956.c lib1957.c lib1958.c lib1959.c lib1960.c lib1964.c lib1965.c lib1970.c lib1971.c lib1972.c lib1973.c lib1974.c lib1975.c lib1977.c lib1978.c lib2023.c lib2032.c lib2082.c lib2301.c lib2302.c lib2304.c lib2306.c lib2308.c lib2309.c lib2402.c lib2404.c lib2405.c lib2502.c lib2504.c lib2505.c lib2506.c lib2700.c lib3010.c lib3025.c lib3026.c lib3027.c lib3033.c lib3034.c lib3100.c lib3101.c lib3102.c lib3103.c lib3104.c lib3105.c lib3207.c lib3208.c lib500.c lib501.c lib502.c lib503.c lib504.c lib505.c lib506.c lib507.c lib508.c lib509.c lib510.c lib511.c lib512.c lib513.c lib514.c lib515.c lib516.c lib517.c lib518.c lib519.c lib520.c lib521.c lib523.c lib524.c lib525.c lib526.c lib530.c lib533.c lib536.c lib537.c lib539.c lib540.c lib541.c lib542.c lib543.c lib544.c lib547.c lib549.c lib552.c lib553.c lib554.c lib555.c lib556.c lib557.c lib558.c lib559.c lib560.c lib562.c lib564.c lib566.c lib567.c lib568.c lib569.c lib570.c lib571.c lib572.c lib573.c lib574.c lib575.c lib576.c lib578.c lib579.c lib582.c lib583.c lib586.c lib589.c lib590.c lib591.c lib597.c lib598.c lib599.c lib643.c lib650.c lib651.c lib652.c lib653.c lib654.c lib655.c lib658.c lib659.c lib661.c lib666.c lib667.c lib668.c lib670.c lib674.c lib676.c lib677.c lib678.c lib694.c lib695.c lib751.c lib753.c lib757.c lib758.c lib766.c memptr.c mk-lib1521.pl test1013.pl test1022.pl test307.pl test610.pl test613.pl testtrace.c testtrace.h testutil.c testutil.h unitcheck.hserver
.checksrc .gitignore CMakeLists.txt Makefile.am Makefile.inc dnsd.c first.c first.h getpart.c mqttd.c resolve.c rtspd.c sockfilt.c socksd.c sws.c tftpd.c util.ctunit
.gitignore CMakeLists.txt Makefile.am Makefile.inc README.md tool1394.c tool1604.c tool1621.c tool1622.c tool1623.c tool1720.cunit
.gitignore CMakeLists.txt Makefile.am Makefile.inc README.md unit1300.c unit1302.c unit1303.c unit1304.c unit1305.c unit1307.c unit1309.c unit1323.c unit1330.c unit1395.c unit1396.c unit1397.c unit1398.c unit1399.c unit1600.c unit1601.c unit1602.c unit1603.c unit1605.c unit1606.c unit1607.c unit1608.c unit1609.c unit1610.c unit1611.c unit1612.c unit1614.c unit1615.c unit1616.c unit1620.c unit1625.c unit1626.c unit1627.c unit1636.c unit1650.c unit1651.c unit1652.c unit1653.c unit1654.c unit1655.c unit1656.c unit1657.c unit1658.c unit1660.c unit1661.c unit1663.c unit1664.c unit1666.c unit1667.c unit1668.c unit1669.c unit1674.c unit1675.c unit1676.c unit1979.c unit1980.c unit2600.c unit2601.c unit2602.c unit2603.c unit2604.c unit2605.c unit3200.c unit3205.c unit3211.c unit3212.c unit3213.c unit3214.c unit3216.c unit3219.c unit3300.c unit3301.c unit3302.cexamples
.env config.ini crypto_test.lua env_test.lua fs_example.lua http_server.lua https_test.lua ini_example.lua json.lua log.lua path_fs_example.lua process_example.lua request_download.lua request_test.lua run_all.lua sqlite_example.lua sqlite_http_template.lua stash_test.lua template_test.lua timer.lua websocket.luainiparser
example
iniexample.c iniwrite.c parse.c twisted-errors.ini twisted-genhuge.py twisted-ofkey.ini twisted-ofval.ini twisted.initest
CMakeLists.txt test_dictionary.c test_iniparser.c unity-config.yml unity_config.hjinjac
libjinjac
src
CMakeLists.txt ast.c ast.h block_statement.c block_statement.h buffer.c buffer.h buildin.c buildin.h common.h convert.c convert.h flex_decl.h jfunction.c jfunction.h jinja_expression.l jinja_expression.y jinjac_parse.c jinjac_parse.h jinjac_stream.c jinjac_stream.h jlist.c jlist.h jobject.c jobject.h parameter.c parameter.h str_obj.c str_obj.h trace.c trace.htest
.gitignore CMakeLists.txt autotest.rb test_01.expected test_01.jinja test_01b.expected test_01b.jinja test_01c.expected test_01c.jinja test_01d.expected test_01d.jinja test_02.expected test_02.jinja test_03.expected test_03.jinja test_04.expected test_04.jinja test_05.expected test_05.jinja test_06.expected test_06.jinja test_07.expected test_07.jinja test_08.expected test_08.jinja test_08b.expected test_08b.jinja test_09.expected test_09.jinja test_10.expected test_10.jinja test_11.expected test_11.jinja test_12.expected test_12.jinja test_13.expected test_13.jinja test_14.expected test_14.jinja test_15.expected test_15.jinja test_16.expected test_16.jinja test_17.expected test_17.jinja test_18.expected test_18.jinja test_18b.expected test_18b.jinja test_18c.expected test_18c.jinja test_19.expected test_19.jinja test_19b.expected test_19b.jinja test_19c.expected test_19c.jinja test_19d.expected test_19d.jinja test_19e.expected test_19e.jinja test_19f.expected test_19f.jinja test_20.expected test_20.jinja test_21.expected test_21.jinja test_22.expected test_22.jinja test_22a.expected test_22a.jinja test_22b.expected test_22b.jinja test_23.expected test_23.jinja test_24.expected test_24.jinjalibev
Changes LICENSE Makefile Makefile.am Makefile.in README Symbols.ev Symbols.event aclocal.m4 autogen.sh compile config.guess config.h config.h.in config.status config.sub configure configure.ac depcomp ev++.h ev.3 ev.c ev.h ev.pod ev_epoll.c ev_kqueue.c ev_poll.c ev_port.c ev_select.c ev_vars.h ev_win32.c ev_wrap.h event.c event.h install-sh libev.m4 libtool ltmain.sh missing mkinstalldirs stamp-h1luajit
doc
bluequad-print.css bluequad.css contact.html ext_buffer.html ext_c_api.html ext_ffi.html ext_ffi_api.html ext_ffi_semantics.html ext_ffi_tutorial.html ext_jit.html ext_profiler.html extensions.html install.html luajit.html running.htmldynasm
dasm_arm.h dasm_arm.lua dasm_arm64.h dasm_arm64.lua dasm_mips.h dasm_mips.lua dasm_mips64.lua dasm_ppc.h dasm_ppc.lua dasm_proto.h dasm_x64.lua dasm_x86.h dasm_x86.lua dynasm.luasrc
host
.gitignore README buildvm.c buildvm.h buildvm_asm.c buildvm_fold.c buildvm_lib.c buildvm_libbc.h buildvm_peobj.c genlibbc.lua genminilua.lua genversion.lua minilua.cjit
.gitignore bc.lua bcsave.lua dis_arm.lua dis_arm64.lua dis_arm64be.lua dis_mips.lua dis_mips64.lua dis_mips64el.lua dis_mips64r6.lua dis_mips64r6el.lua dis_mipsel.lua dis_ppc.lua dis_x64.lua dis_x86.lua dump.lua p.lua v.lua zone.luawolfssl
.github
workflows
ada.yml arduino.yml async-examples.yml async.yml atecc608-sim.yml bind.yml cmake-autoconf.yml cmake.yml codespell.yml coverity-scan-fixes.yml cryptocb-only.yml curl.yml cyrus-sasl.yml disable-pk-algs.yml docker-Espressif.yml docker-OpenWrt.yml emnet-nonblock.yml fil-c.yml freertos-mem-track.yml gencertbuf.yml grpc.yml haproxy.yml hostap-vm.yml intelasm-c-fallback.yml ipmitool.yml jwt-cpp.yml krb5.yml libspdm.yml libssh2.yml libvncserver.yml linuxkm.yml macos-apple-native-cert-validation.yml mbedtls.sh mbedtls.yml membrowse-comment.yml membrowse-onboard.yml membrowse-report.yml memcached.sh memcached.yml mono.yml mosquitto.yml msmtp.yml msys2.yml multi-arch.yml multi-compiler.yml net-snmp.yml nginx.yml no-malloc.yml no-tls.yml nss.sh nss.yml ntp.yml ocsp.yml openldap.yml openssh.yml openssl-ech.yml opensslcoexist.yml openvpn.yml os-check.yml packaging.yml pam-ipmi.yml pq-all.yml pr-commit-check.yml psk.yml puf.yml python.yml rng-tools.yml rust-wrapper.yml se050-sim.yml smallStackSize.yml socat.yml softhsm.yml sssd.yml stm32-sim.yml stsafe-a120-sim.yml stunnel.yml symbol-prefixes.yml threadx.yml tls-anvil.yml trackmemory.yml watcomc.yml win-csharp-test.yml wolfCrypt-Wconversion.yml wolfboot-integration.yml wolfsm.yml xcode.yml zephyr-4.x.yml zephyr.ymlIDE
ARDUINO
Arduino_README_prepend.md README.md include.am keywords.txt library.properties.template wolfssl-arduino.cpp wolfssl-arduino.sh wolfssl.hECLIPSE
Espressif
ESP-IDF
examples
template
CMakeLists.txt Makefile README.md partitions_singleapp_large.csv sdkconfig.defaults sdkconfig.defaults.esp8266wolfssl_benchmark
VisualGDB
wolfssl_benchmark_IDF_v4.4_ESP32.sln wolfssl_benchmark_IDF_v4.4_ESP32.vgdbproj wolfssl_benchmark_IDF_v5_ESP32.sln wolfssl_benchmark_IDF_v5_ESP32.vgdbproj wolfssl_benchmark_IDF_v5_ESP32C3.sln wolfssl_benchmark_IDF_v5_ESP32C3.vgdbproj wolfssl_benchmark_IDF_v5_ESP32S3.sln wolfssl_benchmark_IDF_v5_ESP32S3.vgdbprojwolfssl_client
CMakeLists.txt Makefile README.md README_server_sm.md partitions_singleapp_large.csv sdkconfig.defaults sdkconfig.defaults.esp32c2 sdkconfig.defaults.esp8266 wolfssl_client_ESP8266.vgdbprojwolfssl_server
CMakeLists.txt Makefile README.md README_server_sm.md partitions_singleapp_large.csv sdkconfig.defaults sdkconfig.defaults.esp32c2 sdkconfig.defaults.esp8266 wolfssl_server_ESP8266.vgdbprojwolfssl_test
VisualGDB
wolfssl_test-IDF_v5_ESP32.sln wolfssl_test-IDF_v5_ESP32.vgdbproj wolfssl_test-IDF_v5_ESP32C3.sln wolfssl_test-IDF_v5_ESP32C3.vgdbproj wolfssl_test-IDF_v5_ESP32C6.sln wolfssl_test-IDF_v5_ESP32C6.vgdbproj wolfssl_test_IDF_v5_ESP32S3.sln wolfssl_test_IDF_v5_ESP32S3.vgdbprojGCC-ARM
Makefile Makefile.bench Makefile.client Makefile.common Makefile.server Makefile.static Makefile.test README.md include.am linker.ld linker_fips.ldIAR-EWARM
embOS
SAMV71_XULT
embOS_SAMV71_XULT_user_settings
user_settings.h user_settings_simple_example.h user_settings_verbose_example.hembOS_wolfcrypt_benchmark_SAMV71_XULT
README_wolfcrypt_benchmark wolfcrypt_benchmark.ewd wolfcrypt_benchmark.ewpINTIME-RTOS
Makefile README.md include.am libwolfssl.c libwolfssl.vcxproj user_settings.h wolfExamples.c wolfExamples.h wolfExamples.sln wolfExamples.vcxproj wolfssl-lib.sln wolfssl-lib.vcxprojMQX
Makefile README-jp.md README.md client-tls.c include.am server-tls.c user_config.h user_settings.hMSVS-2019-AZSPHERE
wolfssl_new_azsphere
.gitignore CMakeLists.txt CMakeSettings.json app_manifest.json applibs_versions.h launch.vs.json main.cNETOS
Makefile.wolfcrypt.inc README.md include.am user_settings.h user_settings.h-cert2425 user_settings.h-cert3389 wolfssl_netos_custom.cPlatformIO
examples
wolfssl_benchmark
CMakeLists.txt README.md platformio.ini sdkconfig.defaults wolfssl_benchmark.code-workspaceROWLEY-CROSSWORKS-ARM
Kinetis_FlashPlacement.xml README.md arm_startup.c benchmark_main.c hw.h include.am kinetis_hw.c retarget.c test_main.c user_settings.h wolfssl.hzp wolfssl_ltc.hzpRenesas
e2studio
RA6M3
README.md README_APRA6M_en.md README_APRA6M_jp.md include.amRX72N
EnvisionKit
Simple
README_EN.md README_JP.mdwolfssl_demo
key_data.c key_data.h user_settings.h wolfssl_demo.c wolfssl_demo.h wolfssl_tsip_unit_test.cSTM32Cube
README.md STM32_Benchmarks.md default_conf.ftl include.am main.c wolfssl_example.c wolfssl_example.hWIN
README.txt include.am test.vcxproj user_settings.h user_settings_dtls.h wolfssl-fips.sln wolfssl-fips.vcxprojWIN-SRTP-KDF-140-3
README.txt include.am resource.h test.vcxproj user_settings.h wolfssl-fips.rc wolfssl-fips.sln wolfssl-fips.vcxprojWIN10
README.txt include.am resource.h test.vcxproj user_settings.h wolfssl-fips.rc wolfssl-fips.sln wolfssl-fips.vcxprojXCODE
Benchmark
include.amXilinxSDK
README.md bench.sh combine.sh eclipse_formatter_profile.xml graph.sh include.am user_settings.h wolfssl_example.capple-universal
wolfssl-multiplatform
iotsafe
Makefile README.md ca-cert.c devices.c devices.h include.am main.c memory-tls.c startup.c target.ld user_settings.hmynewt
README.md apps.wolfcrypttest.pkg.yml crypto.wolfssl.pkg.yml crypto.wolfssl.syscfg.yml include.am setup.shcerts
1024
ca-cert.der ca-cert.pem ca-key.der ca-key.pem client-cert.der client-cert.pem client-key.der client-key.pem client-keyPub.der dh1024.der dh1024.pem dsa-pub-1024.pem dsa1024.der dsa1024.pem include.am rsa1024.der server-cert.der server-cert.pem server-key.der server-key.pemcrl
extra-crls
ca-int-cert-revoked.pem claim-root.pem crl_critical_entry.pem crlnum_57oct.pem crlnum_64oct.pem general-server-crl.pem large_crlnum.pem large_crlnum2.pemdilithium
bench_dilithium_level2_key.der bench_dilithium_level3_key.der bench_dilithium_level5_key.der include.amecc
bp256r1-key.der bp256r1-key.pem ca-secp256k1-cert.pem ca-secp256k1-key.pem client-bp256r1-cert.der client-bp256r1-cert.pem client-secp256k1-cert.der client-secp256k1-cert.pem genecc.sh include.am secp256k1-key.der secp256k1-key.pem secp256k1-param.pem secp256k1-privkey.der secp256k1-privkey.pem server-bp256r1-cert.der server-bp256r1-cert.pem server-secp256k1-cert.der server-secp256k1-cert.pem server2-secp256k1-cert.der server2-secp256k1-cert.pem wolfssl.cnf wolfssl_384.cnfed25519
ca-ed25519-key.der ca-ed25519-key.pem ca-ed25519-priv.der ca-ed25519-priv.pem ca-ed25519.der ca-ed25519.pem client-ed25519-key.der client-ed25519-key.pem client-ed25519-priv.der client-ed25519-priv.pem client-ed25519.der client-ed25519.pem eddsa-ed25519.der eddsa-ed25519.pem gen-ed25519-certs.sh gen-ed25519-keys.sh gen-ed25519.sh include.am root-ed25519-key.der root-ed25519-key.pem root-ed25519-priv.der root-ed25519-priv.pem root-ed25519.der root-ed25519.pem server-ed25519-cert.pem server-ed25519-key.der server-ed25519-key.pem server-ed25519-priv.der server-ed25519-priv.pem server-ed25519.der server-ed25519.pemed448
ca-ed448-key.der ca-ed448-key.pem ca-ed448-priv.der ca-ed448-priv.pem ca-ed448.der ca-ed448.pem client-ed448-key.der client-ed448-key.pem client-ed448-priv.der client-ed448-priv.pem client-ed448.der client-ed448.pem gen-ed448-certs.sh gen-ed448-keys.sh include.am root-ed448-key.der root-ed448-key.pem root-ed448-priv.der root-ed448-priv.pem root-ed448.der root-ed448.pem server-ed448-cert.pem server-ed448-key.der server-ed448-key.pem server-ed448-priv.der server-ed448-priv.pem server-ed448.der server-ed448.pemexternal
DigiCertGlobalRootCA.pem README.txt ca-digicert-ev.pem ca-globalsign-root.pem ca-google-root.pem ca_collection.pem include.amintermediate
ca_false_intermediate
gentestcert.sh int_ca.key server.key test_ca.key test_ca.pem test_int_not_cacert.pem test_sign_bynoca_srv.pem wolfssl_base.conf wolfssl_srv.conflms
bc_hss_L2_H5_W8_root.der bc_hss_L3_H5_W4_root.der bc_lms_chain_ca.der bc_lms_chain_leaf.der bc_lms_native_bc_root.der bc_lms_sha256_h10_w8_root.der bc_lms_sha256_h5_w4_root.der include.ammldsa
README.txt include.am mldsa44-cert.der mldsa44-cert.pem mldsa44-key.pem mldsa44_bare-priv.der mldsa44_bare-seed.der mldsa44_oqskeypair.der mldsa44_priv-only.der mldsa44_pub-spki.der mldsa44_seed-only.der mldsa44_seed-priv.der mldsa65-cert.der mldsa65-cert.pem mldsa65-key.pem mldsa65_bare-priv.der mldsa65_bare-seed.der mldsa65_oqskeypair.der mldsa65_priv-only.der mldsa65_pub-spki.der mldsa65_seed-only.der mldsa65_seed-priv.der mldsa87-cert.der mldsa87-cert.pem mldsa87-key.pem mldsa87_bare-priv.der mldsa87_bare-seed.der mldsa87_oqskeypair.der mldsa87_priv-only.der mldsa87_pub-spki.der mldsa87_seed-only.der mldsa87_seed-priv.derocsp
imposter-root-ca-cert.der imposter-root-ca-cert.pem imposter-root-ca-key.der imposter-root-ca-key.pem include.am index-ca-and-intermediate-cas.txt index-ca-and-intermediate-cas.txt.attr index-intermediate1-ca-issued-certs.txt index-intermediate1-ca-issued-certs.txt.attr index-intermediate2-ca-issued-certs.txt index-intermediate2-ca-issued-certs.txt.attr index-intermediate3-ca-issued-certs.txt index-intermediate3-ca-issued-certs.txt.attr intermediate1-ca-cert.der intermediate1-ca-cert.pem intermediate1-ca-key.der intermediate1-ca-key.pem intermediate2-ca-cert.der intermediate2-ca-cert.pem intermediate2-ca-key.der intermediate2-ca-key.pem intermediate3-ca-cert.der intermediate3-ca-cert.pem intermediate3-ca-key.der intermediate3-ca-key.pem ocsp-responder-cert.der ocsp-responder-cert.pem ocsp-responder-key.der ocsp-responder-key.pem openssl.cnf renewcerts-for-test.sh renewcerts.sh root-ca-cert.der root-ca-cert.pem root-ca-crl.pem root-ca-key.der root-ca-key.pem server1-cert.der server1-cert.pem server1-chain-noroot.pem server1-key.der server1-key.pem server2-cert.der server2-cert.pem server2-key.der server2-key.pem server3-cert.der server3-cert.pem server3-key.der server3-key.pem server4-cert.der server4-cert.pem server4-key.der server4-key.pem server5-cert.der server5-cert.pem server5-key.der server5-key.pem test-leaf-response.der test-multi-response.der test-response-nointern.der test-response-rsapss.der test-response.derp521
ca-p521-key.der ca-p521-key.pem ca-p521-priv.der ca-p521-priv.pem ca-p521.der ca-p521.pem client-p521-key.der client-p521-key.pem client-p521-priv.der client-p521-priv.pem client-p521.der client-p521.pem gen-p521-certs.sh gen-p521-keys.sh include.am root-p521-key.der root-p521-key.pem root-p521-priv.der root-p521-priv.pem root-p521.der root-p521.pem server-p521-cert.pem server-p521-key.der server-p521-key.pem server-p521-priv.der server-p521-priv.pem server-p521.der server-p521.pemrpk
client-cert-rpk.der client-ecc-cert-rpk.der include.am server-cert-rpk.der server-ecc-cert-rpk.derrsapss
ca-3072-rsapss-key.der ca-3072-rsapss-key.pem ca-3072-rsapss-priv.der ca-3072-rsapss-priv.pem ca-3072-rsapss.der ca-3072-rsapss.pem ca-rsapss-key.der ca-rsapss-key.pem ca-rsapss-priv.der ca-rsapss-priv.pem ca-rsapss.der ca-rsapss.pem client-3072-rsapss-key.der client-3072-rsapss-key.pem client-3072-rsapss-priv.der client-3072-rsapss-priv.pem client-3072-rsapss.der client-3072-rsapss.pem client-rsapss-key.der client-rsapss-key.pem client-rsapss-priv.der client-rsapss-priv.pem client-rsapss.der client-rsapss.pem gen-rsapss-keys.sh include.am renew-rsapss-certs.sh root-3072-rsapss-key.der root-3072-rsapss-key.pem root-3072-rsapss-priv.der root-3072-rsapss-priv.pem root-3072-rsapss.der root-3072-rsapss.pem root-rsapss-key.der root-rsapss-key.pem root-rsapss-priv.der root-rsapss-priv.pem root-rsapss.der root-rsapss.pem server-3072-rsapss-cert.pem server-3072-rsapss-key.der server-3072-rsapss-key.pem server-3072-rsapss-priv.der server-3072-rsapss-priv.pem server-3072-rsapss.der server-3072-rsapss.pem server-mix-rsapss-cert.pem server-rsapss-cert.pem server-rsapss-key.der server-rsapss-key.pem server-rsapss-priv.der server-rsapss-priv.pem server-rsapss.der server-rsapss.pemslhdsa
bench_slhdsa_sha2_128f_key.der bench_slhdsa_sha2_128s_key.der bench_slhdsa_sha2_192f_key.der bench_slhdsa_sha2_192s_key.der bench_slhdsa_sha2_256f_key.der bench_slhdsa_sha2_256s_key.der bench_slhdsa_shake128f_key.der bench_slhdsa_shake128s_key.der bench_slhdsa_shake192f_key.der bench_slhdsa_shake192s_key.der bench_slhdsa_shake256f_key.der bench_slhdsa_shake256s_key.der client-mldsa44-priv.pem client-mldsa44-sha2.der client-mldsa44-sha2.pem client-mldsa44-shake.der client-mldsa44-shake.pem gen-slhdsa-mldsa-certs.sh include.am root-slhdsa-sha2-128s-priv.der root-slhdsa-sha2-128s-priv.pem root-slhdsa-sha2-128s.der root-slhdsa-sha2-128s.pem root-slhdsa-shake-128s-priv.der root-slhdsa-shake-128s-priv.pem root-slhdsa-shake-128s.der root-slhdsa-shake-128s.pem server-mldsa44-priv.pem server-mldsa44-sha2.der server-mldsa44-sha2.pem server-mldsa44-shake.der server-mldsa44-shake.pemsm2
ca-sm2-key.der ca-sm2-key.pem ca-sm2-priv.der ca-sm2-priv.pem ca-sm2.der ca-sm2.pem client-sm2-key.der client-sm2-key.pem client-sm2-priv.der client-sm2-priv.pem client-sm2.der client-sm2.pem fix_sm2_spki.py gen-sm2-certs.sh gen-sm2-keys.sh include.am root-sm2-key.der root-sm2-key.pem root-sm2-priv.der root-sm2-priv.pem root-sm2.der root-sm2.pem self-sm2-cert.pem self-sm2-key.pem self-sm2-priv.pem server-sm2-cert.der server-sm2-cert.pem server-sm2-key.der server-sm2-key.pem server-sm2-priv.der server-sm2-priv.pem server-sm2.der server-sm2.pemstatickeys
dh-ffdhe2048-params.pem dh-ffdhe2048-pub.der dh-ffdhe2048-pub.pem dh-ffdhe2048.der dh-ffdhe2048.pem ecc-secp256r1.der ecc-secp256r1.pem gen-static.sh include.am x25519-pub.der x25519-pub.pem x25519.der x25519.pemtest
catalog.txt cert-bad-neg-int.der cert-bad-oid.der cert-bad-utf8.der cert-ext-ia.cfg cert-ext-ia.der cert-ext-ia.pem cert-ext-joi.cfg cert-ext-joi.der cert-ext-joi.pem cert-ext-mnc.der cert-ext-multiple.cfg cert-ext-multiple.der cert-ext-multiple.pem cert-ext-nc-combined.der cert-ext-nc-combined.pem cert-ext-nc.cfg cert-ext-nc.der cert-ext-nc.pem cert-ext-ncdns.der cert-ext-ncdns.pem cert-ext-ncip.der cert-ext-ncip.pem cert-ext-ncmixed.der cert-ext-ncmulti.der cert-ext-ncmulti.pem cert-ext-ncrid.der cert-ext-ncrid.pem cert-ext-nct.cfg cert-ext-nct.der cert-ext-nct.pem cert-ext-ndir-exc.cfg cert-ext-ndir-exc.der cert-ext-ndir-exc.pem cert-ext-ndir.cfg cert-ext-ndir.der cert-ext-ndir.pem cert-ext-ns.der cert-over-max-altnames.cfg cert-over-max-altnames.der cert-over-max-altnames.pem cert-over-max-nc.cfg cert-over-max-nc.der cert-over-max-nc.pem client-ecc-cert-ski.hex cn-ip-literal.der cn-ip-wildcard.der crit-cert.pem crit-key.pem dh1024.der dh1024.pem dh512.der dh512.pem digsigku.pem encrypteddata.msg gen-badsig.sh gen-ext-certs.sh gen-testcerts.sh include.am kari-keyid-cms.msg ktri-keyid-cms.msg ossl-trusted-cert.pem server-badaltname.der server-badaltname.pem server-badaltnull.der server-badaltnull.pem server-badcn.der server-badcn.pem server-badcnnull.der server-badcnnull.pem server-cert-ecc-badsig.der server-cert-ecc-badsig.pem server-cert-rsa-badsig.der server-cert-rsa-badsig.pem server-duplicate-policy.pem server-garbage.der server-garbage.pem server-goodalt.der server-goodalt.pem server-goodaltwild.der server-goodaltwild.pem server-goodcn.der server-goodcn.pem server-goodcnwild.der server-goodcnwild.pem server-localhost.der server-localhost.pem smime-test-canon.p7s smime-test-multipart-badsig.p7s smime-test-multipart.p7s smime-test.p7stest-pathlen
assemble-chains.sh chainA-ICA1-key.pem chainA-ICA1-pathlen0.pem chainA-assembled.pem chainA-entity-key.pem chainA-entity.pem chainB-ICA1-key.pem chainB-ICA1-pathlen0.pem chainB-ICA2-key.pem chainB-ICA2-pathlen1.pem chainB-assembled.pem chainB-entity-key.pem chainB-entity.pem chainC-ICA1-key.pem chainC-ICA1-pathlen1.pem chainC-assembled.pem chainC-entity-key.pem chainC-entity.pem chainD-ICA1-key.pem chainD-ICA1-pathlen127.pem chainD-assembled.pem chainD-entity-key.pem chainD-entity.pem chainE-ICA1-key.pem chainE-ICA1-pathlen128.pem chainE-assembled.pem chainE-entity-key.pem chainE-entity.pem chainF-ICA1-key.pem chainF-ICA1-pathlen1.pem chainF-ICA2-key.pem chainF-ICA2-pathlen0.pem chainF-assembled.pem chainF-entity-key.pem chainF-entity.pem chainG-ICA1-key.pem chainG-ICA1-pathlen0.pem chainG-ICA2-key.pem chainG-ICA2-pathlen1.pem chainG-ICA3-key.pem chainG-ICA3-pathlen99.pem chainG-ICA4-key.pem chainG-ICA4-pathlen5.pem chainG-ICA5-key.pem chainG-ICA5-pathlen20.pem chainG-ICA6-key.pem chainG-ICA6-pathlen10.pem chainG-ICA7-key.pem chainG-ICA7-pathlen100.pem chainG-assembled.pem chainG-entity-key.pem chainG-entity.pem chainH-ICA1-key.pem chainH-ICA1-pathlen0.pem chainH-ICA2-key.pem chainH-ICA2-pathlen2.pem chainH-ICA3-key.pem chainH-ICA3-pathlen2.pem chainH-ICA4-key.pem chainH-ICA4-pathlen2.pem chainH-assembled.pem chainH-entity-key.pem chainH-entity.pem chainI-ICA1-key.pem chainI-ICA1-no_pathlen.pem chainI-ICA2-key.pem chainI-ICA2-no_pathlen.pem chainI-ICA3-key.pem chainI-ICA3-pathlen2.pem chainI-assembled.pem chainI-entity-key.pem chainI-entity.pem chainJ-ICA1-key.pem chainJ-ICA1-no_pathlen.pem chainJ-ICA2-key.pem chainJ-ICA2-no_pathlen.pem chainJ-ICA3-key.pem chainJ-ICA3-no_pathlen.pem chainJ-ICA4-key.pem chainJ-ICA4-pathlen2.pem chainJ-assembled.pem chainJ-entity-key.pem chainJ-entity.pem include.am refreshkeys.shtest-serial0
ee_normal.pem ee_serial0.pem generate_certs.sh include.am intermediate_serial0.pem root_serial0.pem root_serial0_key.pem selfsigned_nonca_serial0.pemxmss
bc_xmss_chain_ca.der bc_xmss_chain_leaf.der bc_xmss_sha2_10_256_root.der bc_xmss_sha2_16_256_root.der bc_xmssmt_sha2_20_2_256_root.der bc_xmssmt_sha2_20_4_256_root.der bc_xmssmt_sha2_40_8_256_root.der include.amcmake
Config.cmake.in README.md config.in functions.cmake include.am options.h.in wolfssl-config-version.cmake.in wolfssl-targets.cmake.indebian
changelog.in control.in copyright include.am libwolfssl-dev.install libwolfssl.install rules.indoc
dox_comments
header_files
aes.h arc4.h ascon.h asn.h asn_public.h blake2.h bn.h camellia.h chacha.h chacha20_poly1305.h cmac.h coding.h compress.h cryptocb.h curve25519.h curve448.h des3.h dh.h doxygen_groups.h doxygen_pages.h dsa.h ecc.h eccsi.h ed25519.h ed448.h error-crypt.h evp.h hash.h hmac.h iotsafe.h kdf.h logging.h md2.h md4.h md5.h memory.h ocsp.h pem.h pkcs11.h pkcs7.h poly1305.h psa.h puf.h pwdbased.h quic.h random.h ripemd.h rsa.h sakke.h sha.h sha256.h sha3.h sha512.h signature.h siphash.h srp.h ssl.h tfm.h types.h wc_encrypt.h wc_port.h wc_she.h wc_slhdsa.h wolfio.hheader_files-ja
aes.h arc4.h ascon.h asn.h asn_public.h blake2.h bn.h camellia.h chacha.h chacha20_poly1305.h cmac.h coding.h compress.h cryptocb.h curve25519.h curve448.h des3.h dh.h doxygen_groups.h doxygen_pages.h dsa.h ecc.h eccsi.h ed25519.h ed448.h error-crypt.h evp.h hash.h hmac.h iotsafe.h kdf.h logging.h md2.h md4.h md5.h memory.h ocsp.h pem.h pkcs11.h pkcs7.h poly1305.h psa.h pwdbased.h quic.h random.h ripemd.h rsa.h sakke.h sha.h sha256.h sha3.h sha512.h signature.h siphash.h srp.h ssl.h tfm.h types.h wc_encrypt.h wc_port.h wolfio.hexamples
async
Makefile README.md async_client.c async_server.c async_tls.c async_tls.h include.am user_settings.hconfigs
README.md include.am user_settings_EBSnet.h user_settings_all.h user_settings_arduino.h user_settings_baremetal.h user_settings_ca.h user_settings_curve25519nonblock.h user_settings_dtls13.h user_settings_eccnonblock.h user_settings_espressif.h user_settings_fipsv2.h user_settings_fipsv5.h user_settings_min_ecc.h user_settings_openssl_compat.h user_settings_pkcs7.h user_settings_platformio.h user_settings_pq.h user_settings_rsa_only.h user_settings_stm32.h user_settings_template.h user_settings_tls12.h user_settings_tls13.h user_settings_wolfboot_keytools.h user_settings_wolfssh.h user_settings_wolftpm.hechoclient
echoclient.c echoclient.h echoclient.sln echoclient.vcproj echoclient.vcxproj include.am quitlinuxkm
Kbuild Makefile README.md get_thread_size.c include.am linuxkm-fips-hash-wrapper.sh linuxkm-fips-hash.c linuxkm_memory.c linuxkm_memory.h linuxkm_wc_port.h lkcapi_aes_glue.c lkcapi_dh_glue.c lkcapi_ecdh_glue.c lkcapi_ecdsa_glue.c lkcapi_glue.c lkcapi_rsa_glue.c lkcapi_sha_glue.c module_exports.c.template module_hooks.c pie_redirect_table.c wolfcrypt.lds x86_vector_register_glue.cm4
ax_add_am_macro.m4 ax_am_jobserver.m4 ax_am_macros.m4 ax_append_compile_flags.m4 ax_append_flag.m4 ax_append_link_flags.m4 ax_append_to_file.m4 ax_atomic.m4 ax_bsdkm.m4 ax_check_compile_flag.m4 ax_check_link_flag.m4 ax_compiler_version.m4 ax_count_cpus.m4 ax_create_generic_config.m4 ax_debug.m4 ax_file_escapes.m4 ax_harden_compiler_flags.m4 ax_linuxkm.m4 ax_print_to_file.m4 ax_pthread.m4 ax_require_defined.m4 ax_tls.m4 ax_vcs_checkout.m4 hexversion.m4 lib_socket_nsl.m4 visibility.m4mqx
wolfcrypt_benchmark
ReferencedRSESystems.xml wolfcrypt_benchmark_twrk70f120m_Int_Flash_DDRData_Debug_PnE_U-MultiLink.launch wolfcrypt_benchmark_twrk70f120m_Int_Flash_DDRData_Release_PnE_U-MultiLink.launch wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Debug_JTrace.jlink wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Debug_JTrace.launch wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Debug_PnE_U-MultiLink.launch wolfcrypt_benchmark_twrk70f120m_Int_Flash_SramData_Release_PnE_U-MultiLink.launchwolfcrypt_test
ReferencedRSESystems.xml wolfcrypt_test_twrk70f120m_Int_Flash_DDRData_Debug_PnE_U-MultiLink.launch wolfcrypt_test_twrk70f120m_Int_Flash_DDRData_Release_PnE_U-MultiLink.launch wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Debug_JTrace.jlink wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Debug_JTrace.launch wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Debug_PnE_U-MultiLink.launch wolfcrypt_test_twrk70f120m_Int_Flash_SramData_Release_PnE_U-MultiLink.launchwolfssl_client
ReferencedRSESystems.xml wolfssl_client_twrk70f120m_Int_Flash_DDRData_Debug_PnE_U-MultiLink.launch wolfssl_client_twrk70f120m_Int_Flash_DDRData_Release_PnE_U-MultiLink.launch wolfssl_client_twrk70f120m_Int_Flash_SramData_Debug_JTrace.jlink wolfssl_client_twrk70f120m_Int_Flash_SramData_Debug_JTrace.launch wolfssl_client_twrk70f120m_Int_Flash_SramData_Debug_PnE_U-MultiLink.launch wolfssl_client_twrk70f120m_Int_Flash_SramData_Release_PnE_U-MultiLink.launchscripts
aria-cmake-build-test.sh asn1_oid_sum.pl benchmark.test benchmark_compare.sh cleanup_testfiles.sh crl-gen-openssl.test crl-revoked.test dertoc.pl dtls.test dtlscid.test external.test google.test include.am makedistsmall.sh memtest.sh ocsp-responder-openssl-interop.test ocsp-stapling-with-ca-as-responder.test ocsp-stapling-with-wolfssl-responder.test ocsp-stapling.test ocsp-stapling2.test ocsp-stapling_tls13multi.test ocsp.test openssl.test openssl_srtp.test pem.test ping.test pkcallbacks.test psk.test resume.test rsapss.test sniffer-gen.sh sniffer-ipv6.pcap sniffer-static-rsa.pcap sniffer-testsuite.test sniffer-tls12-keylog.out sniffer-tls12-keylog.pcap sniffer-tls12-keylog.sslkeylog sniffer-tls13-dh-resume.pcap sniffer-tls13-dh.pcap sniffer-tls13-ecc-resume.pcap sniffer-tls13-ecc.pcap sniffer-tls13-hrr.pcap sniffer-tls13-keylog.out sniffer-tls13-keylog.pcap sniffer-tls13-keylog.sslkeylog sniffer-tls13-x25519-resume.pcap sniffer-tls13-x25519.pcap stm32l4-v4_0_1_build.sh tls13.test trusted_peer.test unit.test.in user_settings_asm.shsrc
bio.c conf.c crl.c dtls.c dtls13.c include.am internal.c keys.c ocsp.c pk.c pk_ec.c pk_rsa.c quic.c sniffer.c ssl.c ssl_api_cert.c ssl_api_crl_ocsp.c ssl_api_pk.c ssl_asn1.c ssl_bn.c ssl_certman.c ssl_crypto.c ssl_ech.c ssl_load.c ssl_misc.c ssl_p7p12.c ssl_sess.c ssl_sk.c tls.c tls13.c wolfio.c x509.c x509_str.ctests
api
api.h api_decl.h create_ocsp_test_blobs.py include.am test_aes.c test_aes.h test_arc4.c test_arc4.h test_ascon.c test_ascon.h test_ascon_kats.h test_asn.c test_asn.h test_blake2.c test_blake2.h test_camellia.c test_camellia.h test_certman.c test_certman.h test_chacha.c test_chacha.h test_chacha20_poly1305.c test_chacha20_poly1305.h test_cmac.c test_cmac.h test_curve25519.c test_curve25519.h test_curve448.c test_curve448.h test_des3.c test_des3.h test_dh.c test_dh.h test_digest.h test_dsa.c test_dsa.h test_dtls.c test_dtls.h test_ecc.c test_ecc.h test_ed25519.c test_ed25519.h test_ed448.c test_ed448.h test_evp.c test_evp.h test_evp_cipher.c test_evp_cipher.h test_evp_digest.c test_evp_digest.h test_evp_pkey.c test_evp_pkey.h test_hash.c test_hash.h test_hmac.c test_hmac.h test_md2.c test_md2.h test_md4.c test_md4.h test_md5.c test_md5.h test_mldsa.c test_mldsa.h test_mlkem.c test_mlkem.h test_ocsp.c test_ocsp.h test_ocsp_test_blobs.h test_ossl_asn1.c test_ossl_asn1.h test_ossl_bio.c test_ossl_bio.h test_ossl_bn.c test_ossl_bn.h test_ossl_cipher.c test_ossl_cipher.h test_ossl_dgst.c test_ossl_dgst.h test_ossl_dh.c test_ossl_dh.h test_ossl_dsa.c test_ossl_dsa.h test_ossl_ec.c test_ossl_ec.h test_ossl_ecx.c test_ossl_ecx.h test_ossl_mac.c test_ossl_mac.h test_ossl_obj.c test_ossl_obj.h test_ossl_p7p12.c test_ossl_p7p12.h test_ossl_pem.c test_ossl_pem.h test_ossl_rand.c test_ossl_rand.h test_ossl_rsa.c test_ossl_rsa.h test_ossl_sk.c test_ossl_sk.h test_ossl_x509.c test_ossl_x509.h test_ossl_x509_acert.c test_ossl_x509_acert.h test_ossl_x509_crypto.c test_ossl_x509_crypto.h test_ossl_x509_ext.c test_ossl_x509_ext.h test_ossl_x509_info.c test_ossl_x509_info.h test_ossl_x509_io.c test_ossl_x509_io.h test_ossl_x509_lu.c test_ossl_x509_lu.h test_ossl_x509_name.c test_ossl_x509_name.h test_ossl_x509_pk.c test_ossl_x509_pk.h test_ossl_x509_str.c test_ossl_x509_str.h test_ossl_x509_vp.c test_ossl_x509_vp.h test_pkcs12.c test_pkcs12.h test_pkcs7.c test_pkcs7.h test_poly1305.c test_poly1305.h test_random.c test_random.h test_rc2.c test_rc2.h test_ripemd.c test_ripemd.h test_rsa.c test_rsa.h test_sha.c test_sha.h test_sha256.c test_sha256.h test_sha3.c test_sha3.h test_sha512.c test_sha512.h test_she.c test_she.h test_signature.c test_signature.h test_slhdsa.c test_slhdsa.h test_sm2.c test_sm2.h test_sm3.c test_sm3.h test_sm4.c test_sm4.h test_tls.c test_tls.h test_tls13.c test_tls13.h test_tls_ext.c test_tls_ext.h test_wc_encrypt.c test_wc_encrypt.h test_wolfmath.c test_wolfmath.h test_x509.c test_x509.hwolfcrypt
benchmark
README.md benchmark-VS2022.sln benchmark-VS2022.vcxproj benchmark-VS2022.vcxproj.user benchmark.c benchmark.h benchmark.sln benchmark.vcproj benchmark.vcxproj include.amsrc
port
Espressif
esp_crt_bundle
README.md cacrt_all.pem cacrt_deprecated.pem cacrt_local.pem esp_crt_bundle.c gen_crt_bundle.py pio_install_cryptography.pyRenesas
README.md renesas_common.c renesas_fspsm_aes.c renesas_fspsm_rsa.c renesas_fspsm_sha.c renesas_fspsm_util.c renesas_rx64_hw_sha.c renesas_rx64_hw_util.c renesas_tsip_aes.c renesas_tsip_rsa.c renesas_tsip_sha.c renesas_tsip_util.carm
armv8-32-aes-asm.S armv8-32-aes-asm_c.c armv8-32-chacha-asm.S armv8-32-chacha-asm_c.c armv8-32-curve25519.S armv8-32-curve25519_c.c armv8-32-mlkem-asm.S armv8-32-mlkem-asm_c.c armv8-32-poly1305-asm.S armv8-32-poly1305-asm_c.c armv8-32-sha256-asm.S armv8-32-sha256-asm_c.c armv8-32-sha3-asm.S armv8-32-sha3-asm_c.c armv8-32-sha512-asm.S armv8-32-sha512-asm_c.c armv8-aes-asm.S armv8-aes-asm_c.c armv8-aes.c armv8-chacha-asm.S armv8-chacha-asm_c.c armv8-curve25519.S armv8-curve25519_c.c armv8-mlkem-asm.S armv8-mlkem-asm_c.c armv8-poly1305-asm.S armv8-poly1305-asm_c.c armv8-sha256-asm.S armv8-sha256-asm_c.c armv8-sha256.c armv8-sha3-asm.S armv8-sha3-asm_c.c armv8-sha512-asm.S armv8-sha512-asm_c.c armv8-sha512.c cryptoCell.c cryptoCellHash.c thumb2-aes-asm.S thumb2-aes-asm_c.c thumb2-chacha-asm.S thumb2-chacha-asm_c.c thumb2-curve25519.S thumb2-curve25519_c.c thumb2-mlkem-asm.S thumb2-mlkem-asm_c.c thumb2-poly1305-asm.S thumb2-poly1305-asm_c.c thumb2-sha256-asm.S thumb2-sha256-asm_c.c thumb2-sha3-asm.S thumb2-sha3-asm_c.c thumb2-sha512-asm.S thumb2-sha512-asm_c.ccaam
README.md caam_aes.c caam_doc.pdf caam_driver.c caam_error.c caam_integrity.c caam_qnx.c caam_sha.c wolfcaam_aes.c wolfcaam_cmac.c wolfcaam_ecdsa.c wolfcaam_fsl_nxp.c wolfcaam_hash.c wolfcaam_hmac.c wolfcaam_init.c wolfcaam_qnx.c wolfcaam_rsa.c wolfcaam_seco.c wolfcaam_x25519.cdevcrypto
README.md devcrypto_aes.c devcrypto_ecdsa.c devcrypto_hash.c devcrypto_hmac.c devcrypto_rsa.c devcrypto_x25519.c wc_devcrypto.criscv
riscv-64-aes.c riscv-64-chacha.c riscv-64-poly1305.c riscv-64-sha256.c riscv-64-sha3.c riscv-64-sha512.cwolfssl
openssl
aes.h asn1.h asn1t.h bio.h bn.h buffer.h camellia.h cmac.h cms.h compat_types.h conf.h crypto.h des.h dh.h dsa.h ec.h ec25519.h ec448.h ecdh.h ecdsa.h ed25519.h ed448.h engine.h err.h evp.h fips_rand.h hmac.h include.am kdf.h lhash.h md4.h md5.h modes.h obj_mac.h objects.h ocsp.h opensslconf.h opensslv.h ossl_typ.h pem.h pkcs12.h pkcs7.h rand.h rc4.h ripemd.h rsa.h safestack.h sha.h sha3.h srp.h ssl.h ssl23.h stack.h tls1.h txt_db.h ui.h x509.h x509_vfy.h x509v3.hwolfcrypt
port
Renesas
renesas-fspsm-crypt.h renesas-fspsm-types.h renesas-rx64-hw-crypt.h renesas-tsip-crypt.h renesas_cmn.h renesas_fspsm_internal.h renesas_sync.h renesas_tsip_internal.h renesas_tsip_types.hcaam
caam_driver.h caam_error.h caam_qnx.h wolfcaam.h wolfcaam_aes.h wolfcaam_cmac.h wolfcaam_ecdsa.h wolfcaam_fsl_nxp.h wolfcaam_hash.h wolfcaam_qnx.h wolfcaam_rsa.h wolfcaam_seco.h wolfcaam_sha.h wolfcaam_x25519.hwrapper
Ada
examples
src
aes_verify_main.adb rsa_verify_main.adb sha256_main.adb spark_sockets.adb spark_sockets.ads spark_terminal.adb spark_terminal.ads tls_client.adb tls_client.ads tls_client_main.adb tls_server.adb tls_server.ads tls_server_main.adbtests
src
aes_bindings_tests.adb aes_bindings_tests.ads rsa_verify_bindings_tests.adb rsa_verify_bindings_tests.ads sha256_bindings_tests.adb sha256_bindings_tests.ads tests.adbCSharp
wolfSSL-Example-IOCallbacks
App.config wolfSSL-Example-IOCallbacks.cs wolfSSL-Example-IOCallbacks.csprojwolfSSL-TLS-ServerThreaded
App.config wolfSSL-TLS-ServerThreaded.cs wolfSSL-TLS-ServerThreaded.csprojrust
wolfssl-wolfcrypt
src
aes.rs blake2.rs chacha20_poly1305.rs cmac.rs cmac_mac.rs curve25519.rs dh.rs dilithium.rs ecc.rs ecdsa.rs ed25519.rs ed448.rs fips.rs hkdf.rs hmac.rs hmac_mac.rs kdf.rs lib.rs lms.rs mlkem.rs mlkem_kem.rs pbkdf2_password_hash.rs prf.rs random.rs rsa.rs rsa_pkcs1v15.rs sha.rs sha_digest.rs sys.rstests
test_aes.rs test_blake2.rs test_chacha20_poly1305.rs test_cmac.rs test_cmac_mac.rs test_curve25519.rs test_dh.rs test_dilithium.rs test_ecc.rs test_ecdsa.rs test_ed25519.rs test_ed448.rs test_hkdf.rs test_hmac.rs test_hmac_mac.rs test_kdf.rs test_lms.rs test_mlkem.rs test_mlkem_kem.rs test_pbkdf2_password_hash.rs test_prf.rs test_random.rs test_rsa.rs test_rsa_pkcs1v15.rs test_sha.rs test_sha_digest.rs test_wolfcrypt.rszephyr
samples
wolfssl_benchmark
CMakeLists.txt README install_test.sh prj.conf sample.yaml zephyr_legacy.conf zephyr_v4.1.confwolfssl_test
CMakeLists.txt README install_test.sh prj-no-malloc.conf prj.conf sample.yaml zephyr_legacy.conf zephyr_v4.1.conf
curl/lib/vssh/libssh2.c
raw
1/***************************************************************************
2 * _ _ ____ _
3 * Project ___| | | | _ \| |
4 * / __| | | | |_) | |
5 * | (__| |_| | _ <| |___
6 * \___|\___/|_| \_\_____|
7 *
8 * Copyright (C) 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.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 * SPDX-License-Identifier: curl
22 *
23 ***************************************************************************/
24#include "curl_setup.h"
25
26#ifdef USE_LIBSSH2
27
28/* #define CURL_LIBSSH2_DEBUG */
29
30#ifdef HAVE_NETINET_IN_H
31#include <netinet/in.h>
32#endif
33#ifdef HAVE_ARPA_INET_H
34#include <arpa/inet.h>
35#endif
36#ifdef HAVE_NETDB_H
37#include <netdb.h>
38#endif
39#ifdef __VMS
40#include <in.h>
41#include <inet.h>
42#endif
43
44#include "urldata.h"
45#include "sendf.h"
46#include "curl_trc.h"
47#include "hostip.h"
48#include "progress.h"
49#include "transfer.h"
50#include "vssh/ssh.h"
51#include "url.h"
52#include "cfilters.h"
53#include "connect.h"
54#include "parsedate.h" /* for the week day and month names */
55#include "multiif.h"
56#include "select.h"
57#include "curlx/fopen.h"
58#include "vssh/vssh.h"
59#include "curlx/strparse.h"
60#include "curlx/base64.h" /* for curlx_base64_encode() */
61
62static const char *sftp_libssh2_strerror(unsigned long err)
63{
64 switch(err) {
65 case LIBSSH2_FX_NO_SUCH_FILE:
66 return "No such file or directory";
67
68 case LIBSSH2_FX_PERMISSION_DENIED:
69 return "Permission denied";
70
71 case LIBSSH2_FX_FAILURE:
72 return "Operation failed";
73
74 case LIBSSH2_FX_BAD_MESSAGE:
75 return "Bad message from SFTP server";
76
77 case LIBSSH2_FX_NO_CONNECTION:
78 return "Not connected to SFTP server";
79
80 case LIBSSH2_FX_CONNECTION_LOST:
81 return "Connection to SFTP server lost";
82
83 case LIBSSH2_FX_OP_UNSUPPORTED:
84 return "Operation not supported by SFTP server";
85
86 case LIBSSH2_FX_INVALID_HANDLE:
87 return "Invalid handle";
88
89 case LIBSSH2_FX_NO_SUCH_PATH:
90 return "No such file or directory";
91
92 case LIBSSH2_FX_FILE_ALREADY_EXISTS:
93 return "File already exists";
94
95 case LIBSSH2_FX_WRITE_PROTECT:
96 return "File is write protected";
97
98 case LIBSSH2_FX_NO_MEDIA:
99 return "No media";
100
101 case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM:
102 return "Disk full";
103
104 case LIBSSH2_FX_QUOTA_EXCEEDED:
105 return "User quota exceeded";
106
107 case LIBSSH2_FX_UNKNOWN_PRINCIPLE:
108 return "Unknown principle";
109
110 case LIBSSH2_FX_LOCK_CONFlICT:
111 return "File lock conflict";
112
113 case LIBSSH2_FX_DIR_NOT_EMPTY:
114 return "Directory not empty";
115
116 case LIBSSH2_FX_NOT_A_DIRECTORY:
117 return "Not a directory";
118
119 case LIBSSH2_FX_INVALID_FILENAME:
120 return "Invalid filename";
121
122 case LIBSSH2_FX_LINK_LOOP:
123 return "Link points to itself";
124 }
125 return "Unknown error in libssh2";
126}
127
128static void kbd_callback(const char *name, int name_len,
129 const char *instruction, int instruction_len,
130 int num_prompts,
131 const LIBSSH2_USERAUTH_KBDINT_PROMPT *prompts,
132 LIBSSH2_USERAUTH_KBDINT_RESPONSE *responses,
133 void **abstract)
134{
135 struct Curl_easy *data = (struct Curl_easy *)*abstract;
136
137#ifdef CURL_LIBSSH2_DEBUG
138 curl_mfprintf(stderr, "name=%s\n", name);
139 curl_mfprintf(stderr, "name_len=%d\n", name_len);
140 curl_mfprintf(stderr, "instruction=%s\n", instruction);
141 curl_mfprintf(stderr, "instruction_len=%d\n", instruction_len);
142 curl_mfprintf(stderr, "num_prompts=%d\n", num_prompts);
143#else
144 (void)name;
145 (void)name_len;
146 (void)instruction;
147 (void)instruction_len;
148#endif /* CURL_LIBSSH2_DEBUG */
149 if(num_prompts == 1) {
150 struct connectdata *conn = data->conn;
151 const char *passwd = Curl_creds_passwd(conn->creds);
152 /* this function must allocate memory that can be freed by libssh2, which
153 uses the LIBSSH2_FREE_FUNC callback */
154 responses[0].text = Curl_cstrdup(passwd);
155 responses[0].length =
156 responses[0].text == NULL ? 0 : curlx_uztoui(strlen(passwd));
157 }
158 (void)prompts;
159} /* kbd_callback */
160
161static CURLcode sftp_libssh2_error_to_CURLE(unsigned long err)
162{
163 switch(err) {
164 case LIBSSH2_FX_OK:
165 return CURLE_OK;
166
167 case LIBSSH2_FX_NO_SUCH_FILE:
168 case LIBSSH2_FX_NO_SUCH_PATH:
169 return CURLE_REMOTE_FILE_NOT_FOUND;
170
171 case LIBSSH2_FX_PERMISSION_DENIED:
172 case LIBSSH2_FX_WRITE_PROTECT:
173 case LIBSSH2_FX_LOCK_CONFlICT:
174 return CURLE_REMOTE_ACCESS_DENIED;
175
176 case LIBSSH2_FX_NO_SPACE_ON_FILESYSTEM:
177 case LIBSSH2_FX_QUOTA_EXCEEDED:
178 return CURLE_REMOTE_DISK_FULL;
179
180 case LIBSSH2_FX_FILE_ALREADY_EXISTS:
181 return CURLE_REMOTE_FILE_EXISTS;
182
183 case LIBSSH2_FX_DIR_NOT_EMPTY:
184 return CURLE_QUOTE_ERROR;
185
186 default:
187 break;
188 }
189
190 return CURLE_SSH;
191}
192
193static CURLcode libssh2_session_error_to_CURLE(int err)
194{
195 switch(err) {
196 /* Ordered by order of appearance in libssh2.h */
197 case LIBSSH2_ERROR_NONE:
198 return CURLE_OK;
199
200 /* This is the error returned by libssh2_scp_recv2
201 * on unknown file */
202 case LIBSSH2_ERROR_SCP_PROTOCOL:
203 return CURLE_REMOTE_FILE_NOT_FOUND;
204
205 case LIBSSH2_ERROR_SOCKET_NONE:
206 return CURLE_COULDNT_CONNECT;
207
208 case LIBSSH2_ERROR_ALLOC:
209 return CURLE_OUT_OF_MEMORY;
210
211 case LIBSSH2_ERROR_SOCKET_SEND:
212 return CURLE_SEND_ERROR;
213
214 case LIBSSH2_ERROR_HOSTKEY_INIT:
215 case LIBSSH2_ERROR_HOSTKEY_SIGN:
216 case LIBSSH2_ERROR_PUBLICKEY_UNRECOGNIZED:
217 case LIBSSH2_ERROR_PUBLICKEY_UNVERIFIED:
218 return CURLE_PEER_FAILED_VERIFICATION;
219
220 case LIBSSH2_ERROR_PASSWORD_EXPIRED:
221 return CURLE_LOGIN_DENIED;
222
223 case LIBSSH2_ERROR_SOCKET_TIMEOUT:
224 case LIBSSH2_ERROR_TIMEOUT:
225 return CURLE_OPERATION_TIMEDOUT;
226
227 case LIBSSH2_ERROR_EAGAIN:
228 return CURLE_AGAIN;
229 }
230
231 return CURLE_SSH;
232}
233
234/* These functions are made to use the libcurl memory functions - NOT the
235 debugmem functions, as that leads us to trigger on libssh2 memory leaks
236 that are not ours to care for */
237
238static LIBSSH2_ALLOC_FUNC(my_libssh2_malloc)
239{
240 (void)abstract;
241 return Curl_cmalloc(count);
242}
243
244static LIBSSH2_REALLOC_FUNC(my_libssh2_realloc)
245{
246 (void)abstract;
247 return Curl_crealloc(ptr, count);
248}
249
250static LIBSSH2_FREE_FUNC(my_libssh2_free)
251{
252 (void)abstract;
253 if(ptr) /* ssh2 agent sometimes call free with null ptr */
254 Curl_cfree(ptr);
255}
256
257static int sshkeycallback(CURL *easy,
258 const struct curl_khkey *knownkey, /* known */
259 const struct curl_khkey *foundkey, /* found */
260 enum curl_khmatch match,
261 void *clientp)
262{
263 (void)easy;
264 (void)knownkey;
265 (void)foundkey;
266 (void)clientp;
267
268 /* we only allow perfect matches, and we reject everything else */
269 return (match != CURLKHMATCH_OK) ? CURLKHSTAT_REJECT : CURLKHSTAT_FINE;
270}
271
272static enum curl_khtype convert_ssh2_keytype(int sshkeytype)
273{
274 enum curl_khtype keytype = CURLKHTYPE_UNKNOWN;
275 switch(sshkeytype) {
276 case LIBSSH2_HOSTKEY_TYPE_RSA:
277 keytype = CURLKHTYPE_RSA;
278 break;
279 case LIBSSH2_HOSTKEY_TYPE_DSS:
280 keytype = CURLKHTYPE_DSS;
281 break;
282#ifdef LIBSSH2_HOSTKEY_TYPE_ECDSA_256
283 case LIBSSH2_HOSTKEY_TYPE_ECDSA_256:
284 keytype = CURLKHTYPE_ECDSA;
285 break;
286#endif
287#ifdef LIBSSH2_HOSTKEY_TYPE_ECDSA_384
288 case LIBSSH2_HOSTKEY_TYPE_ECDSA_384:
289 keytype = CURLKHTYPE_ECDSA;
290 break;
291#endif
292#ifdef LIBSSH2_HOSTKEY_TYPE_ECDSA_521
293 case LIBSSH2_HOSTKEY_TYPE_ECDSA_521:
294 keytype = CURLKHTYPE_ECDSA;
295 break;
296#endif
297#ifdef LIBSSH2_HOSTKEY_TYPE_ED25519
298 case LIBSSH2_HOSTKEY_TYPE_ED25519:
299 keytype = CURLKHTYPE_ED25519;
300 break;
301#endif
302 }
303 return keytype;
304}
305
306static CURLcode ssh_knownhost(struct Curl_easy *data,
307 struct ssh_conn *sshc)
308{
309 int sshkeytype = 0;
310 size_t keylen = 0;
311 int rc = 0;
312 CURLcode result = CURLE_OK;
313
314 if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
315 /* we are asked to verify the host against a file */
316 struct connectdata *conn = data->conn;
317 struct libssh2_knownhost *host = NULL;
318 const char *remotekey = libssh2_session_hostkey(sshc->ssh_session,
319 &keylen, &sshkeytype);
320 int keycheck = LIBSSH2_KNOWNHOST_CHECK_FAILURE;
321 int keybit = 0;
322
323 if(remotekey) {
324 /*
325 * A subject to figure out is what hostname we need to pass in here.
326 * What hostname does OpenSSH store in its file if an IDN name is
327 * used?
328 */
329 enum curl_khmatch keymatch;
330 curl_sshkeycallback func =
331 data->set.ssh_keyfunc ? data->set.ssh_keyfunc : sshkeycallback;
332 struct curl_khkey knownkey;
333 struct curl_khkey *knownkeyp = NULL;
334 struct curl_khkey foundkey;
335
336 switch(sshkeytype) {
337 case LIBSSH2_HOSTKEY_TYPE_RSA:
338 keybit = LIBSSH2_KNOWNHOST_KEY_SSHRSA;
339 break;
340 case LIBSSH2_HOSTKEY_TYPE_DSS:
341 keybit = LIBSSH2_KNOWNHOST_KEY_SSHDSS;
342 break;
343 case LIBSSH2_HOSTKEY_TYPE_ECDSA_256:
344 keybit = LIBSSH2_KNOWNHOST_KEY_ECDSA_256;
345 break;
346 case LIBSSH2_HOSTKEY_TYPE_ECDSA_384:
347 keybit = LIBSSH2_KNOWNHOST_KEY_ECDSA_384;
348 break;
349 case LIBSSH2_HOSTKEY_TYPE_ECDSA_521:
350 keybit = LIBSSH2_KNOWNHOST_KEY_ECDSA_521;
351 break;
352 case LIBSSH2_HOSTKEY_TYPE_ED25519:
353 keybit = LIBSSH2_KNOWNHOST_KEY_ED25519;
354 break;
355 default:
356 infof(data, "unsupported key type, cannot check knownhosts");
357 keybit = 0;
358 break;
359 }
360 if(!keybit)
361 /* no check means failure! */
362 rc = CURLKHSTAT_REJECT;
363 else {
364 keycheck = libssh2_knownhost_checkp(sshc->kh,
365 conn->origin->hostname,
366 (conn->origin->port != PORT_SSH) ?
367 conn->origin->port : -1,
368 remotekey, keylen,
369 LIBSSH2_KNOWNHOST_TYPE_PLAIN|
370 LIBSSH2_KNOWNHOST_KEYENC_RAW|
371 keybit,
372 &host);
373
374 infof(data, "SSH host check: %d, key: %s", keycheck,
375 (keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH) ?
376 host->key : "<none>");
377
378 /* setup 'knownkey' */
379 if(keycheck <= LIBSSH2_KNOWNHOST_CHECK_MISMATCH) {
380 knownkey.key = host->key;
381 knownkey.len = 0;
382 knownkey.keytype = convert_ssh2_keytype(sshkeytype);
383 knownkeyp = &knownkey;
384 }
385
386 /* setup 'foundkey' */
387 foundkey.key = remotekey;
388 foundkey.len = keylen;
389 foundkey.keytype = convert_ssh2_keytype(sshkeytype);
390
391 /*
392 * if any of the LIBSSH2_KNOWNHOST_CHECK_* defines and the
393 * curl_khmatch enum are ever modified, we need to introduce a
394 * translation table here!
395 */
396 keymatch = (enum curl_khmatch)keycheck;
397
398 /* Ask the callback how to behave */
399 Curl_set_in_callback(data, TRUE);
400 rc = func(data, knownkeyp, /* from the knownhosts file */
401 &foundkey, /* from the remote host */
402 keymatch, data->set.ssh_keyfunc_userp);
403 Curl_set_in_callback(data, FALSE);
404 }
405 }
406 else
407 /* no remotekey means failure! */
408 rc = CURLKHSTAT_REJECT;
409
410 switch(rc) {
411 default: /* unknown return codes is the same as reject */
412 case CURLKHSTAT_REJECT:
413 myssh_to(data, sshc, SSH_SESSION_FREE);
414 FALLTHROUGH();
415 case CURLKHSTAT_DEFER:
416 /* DEFER means bail out but keep the SSH_HOSTKEY state */
417 result = CURLE_PEER_FAILED_VERIFICATION;
418 break;
419 case CURLKHSTAT_FINE_REPLACE:
420 /* remove old host+key that does not match */
421 if(host)
422 libssh2_knownhost_del(sshc->kh, host);
423 FALLTHROUGH();
424 case CURLKHSTAT_FINE:
425 case CURLKHSTAT_FINE_ADD_TO_FILE:
426 /* proceed */
427 if(keycheck != LIBSSH2_KNOWNHOST_CHECK_MATCH) {
428 /* the found host+key did not match but has been told to be fine
429 anyway so we add it in memory */
430 int addrc = libssh2_knownhost_add(sshc->kh,
431 conn->origin->hostname, NULL,
432 remotekey, keylen,
433 LIBSSH2_KNOWNHOST_TYPE_PLAIN|
434 LIBSSH2_KNOWNHOST_KEYENC_RAW|
435 keybit, NULL);
436 if(addrc)
437 infof(data, "WARNING: adding the known host %s failed",
438 conn->origin->hostname);
439 else if(rc == CURLKHSTAT_FINE_ADD_TO_FILE ||
440 rc == CURLKHSTAT_FINE_REPLACE) {
441 /* now we write the entire in-memory list of known hosts to the
442 known_hosts file */
443 int wrc =
444 libssh2_knownhost_writefile(sshc->kh,
445 data->set.str[STRING_SSH_KNOWNHOSTS],
446 LIBSSH2_KNOWNHOST_FILE_OPENSSH);
447 if(wrc) {
448 infof(data, "WARNING: writing %s failed",
449 data->set.str[STRING_SSH_KNOWNHOSTS]);
450 }
451 }
452 }
453 break;
454 }
455 }
456 return result;
457}
458
459static CURLcode ssh_check_fingerprint(struct Curl_easy *data,
460 struct ssh_conn *sshc)
461{
462 const char *pubkey_md5 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5];
463 const char *pubkey_sha256 = data->set.str[STRING_SSH_HOST_PUBLIC_KEY_SHA256];
464
465 infof(data, "SSH MD5 public key: %s",
466 pubkey_md5 != NULL ? pubkey_md5 : "NULL");
467 infof(data, "SSH SHA256 public key: %s",
468 pubkey_sha256 != NULL ? pubkey_sha256 : "NULL");
469
470 if(pubkey_sha256) {
471 const char *fingerprint = NULL;
472 char *fingerprint_b64 = NULL;
473 size_t fingerprint_b64_len;
474 size_t pub_pos = 0;
475 size_t b64_pos = 0;
476
477 /* The fingerprint points to static storage (!), do not free() it. */
478 fingerprint = libssh2_hostkey_hash(sshc->ssh_session,
479 LIBSSH2_HOSTKEY_HASH_SHA256);
480 if(!fingerprint) {
481 failf(data,
482 "Denied establishing ssh session: SHA256 fingerprint "
483 "not available");
484 myssh_to(data, sshc, SSH_SESSION_FREE);
485 return CURLE_PEER_FAILED_VERIFICATION;
486 }
487
488 /* The length of fingerprint is 32 bytes for SHA256.
489 * See libssh2_hostkey_hash documentation. */
490 if(curlx_base64_encode((const uint8_t *)fingerprint, 32, &fingerprint_b64,
491 &fingerprint_b64_len) != CURLE_OK) {
492 myssh_to(data, sshc, SSH_SESSION_FREE);
493 return CURLE_PEER_FAILED_VERIFICATION;
494 }
495
496 if(!fingerprint_b64) {
497 failf(data, "SHA256 fingerprint could not be encoded");
498 myssh_to(data, sshc, SSH_SESSION_FREE);
499 return CURLE_PEER_FAILED_VERIFICATION;
500 }
501
502 infof(data, "SSH SHA256 fingerprint: %s", fingerprint_b64);
503
504 /* Find the position of any = padding characters in the public key */
505 while((pubkey_sha256[pub_pos] != '=') && pubkey_sha256[pub_pos]) {
506 pub_pos++;
507 }
508
509 /* Find the position of any = padding characters in the base64 coded
510 * hostkey fingerprint */
511 while((fingerprint_b64[b64_pos] != '=') && fingerprint_b64[b64_pos]) {
512 b64_pos++;
513 }
514
515 /* Before we authenticate we check the hostkey's SHA256 fingerprint
516 * against a known fingerprint, if available.
517 */
518 if((pub_pos != b64_pos) ||
519 strncmp(fingerprint_b64, pubkey_sha256, pub_pos)) {
520 failf(data,
521 "Denied establishing ssh session: mismatch SHA256 fingerprint. "
522 "Remote %s is not equal to %s", fingerprint_b64, pubkey_sha256);
523 curlx_free(fingerprint_b64);
524 myssh_to(data, sshc, SSH_SESSION_FREE);
525 return CURLE_PEER_FAILED_VERIFICATION;
526 }
527
528 curlx_free(fingerprint_b64);
529
530 infof(data, "SHA256 checksum match");
531 }
532
533 if(pubkey_md5) {
534 char md5buffer[33];
535 const char *fingerprint;
536
537 fingerprint = libssh2_hostkey_hash(sshc->ssh_session,
538 LIBSSH2_HOSTKEY_HASH_MD5);
539
540 if(fingerprint) {
541 /* The fingerprint points to static storage (!), do not free() it. */
542 int i;
543 for(i = 0; i < 16; i++) {
544 curl_msnprintf(&md5buffer[i * 2], 3, "%02x",
545 (unsigned char)fingerprint[i]);
546 }
547
548 infof(data, "SSH MD5 fingerprint: %s", md5buffer);
549 }
550
551 /* This does NOT verify the length of 'pubkey_md5' separately, which
552 makes the comparison below fail unless it is exactly 32 characters */
553 if(!fingerprint || !curl_strequal(md5buffer, pubkey_md5)) {
554 if(fingerprint) {
555 failf(data,
556 "Denied establishing ssh session: mismatch MD5 fingerprint. "
557 "Remote %s is not equal to %s", md5buffer, pubkey_md5);
558 }
559 else {
560 failf(data,
561 "Denied establishing ssh session: MD5 fingerprint "
562 "not available");
563 }
564 myssh_to(data, sshc, SSH_SESSION_FREE);
565 return CURLE_PEER_FAILED_VERIFICATION;
566 }
567 infof(data, "MD5 checksum match");
568 }
569
570 if(!pubkey_md5 && !pubkey_sha256) {
571 if(data->set.ssh_hostkeyfunc) {
572 size_t keylen = 0;
573 int sshkeytype = 0;
574 int rc = 0;
575 /* we handle the process to the callback */
576 const char *remotekey = libssh2_session_hostkey(sshc->ssh_session,
577 &keylen, &sshkeytype);
578 if(remotekey) {
579 enum curl_khtype keytype = convert_ssh2_keytype(sshkeytype);
580 Curl_set_in_callback(data, TRUE);
581 rc = data->set.ssh_hostkeyfunc(data->set.ssh_hostkeyfunc_userp,
582 (int)keytype, remotekey, keylen);
583 Curl_set_in_callback(data, FALSE);
584 if(rc != CURLKHMATCH_OK) {
585 myssh_to(data, sshc, SSH_SESSION_FREE);
586 return CURLE_PEER_FAILED_VERIFICATION;
587 }
588 }
589 else {
590 myssh_to(data, sshc, SSH_SESSION_FREE);
591 return CURLE_PEER_FAILED_VERIFICATION;
592 }
593 return CURLE_OK;
594 }
595 else {
596 return ssh_knownhost(data, sshc);
597 }
598 }
599 else {
600 /* as we already matched, we skip the check for known hosts */
601 return CURLE_OK;
602 }
603}
604
605/*
606 * ssh_force_knownhost_key_type() checks the known hosts file and try to
607 * force a specific public key type from the server if an entry is found.
608 */
609static CURLcode ssh_force_knownhost_key_type(struct Curl_easy *data,
610 struct ssh_conn *sshc)
611{
612 CURLcode result = CURLE_OK;
613
614 static const char hostkey_method_ssh_ed25519[] = "ssh-ed25519";
615 static const char hostkey_method_ssh_ecdsa_521[] = "ecdsa-sha2-nistp521";
616 static const char hostkey_method_ssh_ecdsa_384[] = "ecdsa-sha2-nistp384";
617 static const char hostkey_method_ssh_ecdsa_256[] = "ecdsa-sha2-nistp256";
618 static const char hostkey_method_ssh_rsa_all[] =
619 "rsa-sha2-256,rsa-sha2-512,ssh-rsa";
620 static const char hostkey_method_ssh_dss[] = "ssh-dss";
621 bool found = FALSE;
622
623 if(sshc->kh &&
624 !data->set.str[STRING_SSH_HOST_PUBLIC_KEY_MD5] &&
625 !data->set.str[STRING_SSH_HOST_PUBLIC_KEY_SHA256]) {
626 struct libssh2_knownhost *store = NULL;
627 struct connectdata *conn = data->conn;
628 /* lets try to find our host in the known hosts file */
629 while(!libssh2_knownhost_get(sshc->kh, &store, store)) {
630 /* For non-standard ports, the name is enclosed in */
631 /* square brackets, followed by a colon and the port */
632 if(store) {
633 if(store->name) {
634 if(store->name[0] == '[') {
635 curl_off_t port;
636 size_t kh_name_size = 0;
637 const char *p;
638 const char *kh_name_end = strstr(store->name, "]:");
639 if(!kh_name_end) {
640 infof(data, "Invalid host pattern %s in %s",
641 store->name, data->set.str[STRING_SSH_KNOWNHOSTS]);
642 continue;
643 }
644 p = kh_name_end + 2; /* start of port number */
645 if(!curlx_str_number(&p, &port, 0xffff) &&
646 (kh_name_end && (port == conn->origin->port))) {
647 kh_name_size = strlen(store->name) - 1 - strlen(kh_name_end);
648 if(strncmp(store->name + 1,
649 conn->origin->hostname, kh_name_size) == 0) {
650 found = TRUE;
651 break;
652 }
653 }
654 }
655 else if(strcmp(store->name, conn->origin->hostname) == 0) {
656 found = TRUE;
657 break;
658 }
659 }
660 else {
661 found = TRUE;
662 break;
663 }
664 }
665 }
666
667 if(found) {
668 int rc;
669 const char *hostkey_method = NULL;
670 infof(data, "Found host %s in %s",
671 conn->origin->hostname, data->set.str[STRING_SSH_KNOWNHOSTS]);
672
673 switch(store->typemask & LIBSSH2_KNOWNHOST_KEY_MASK) {
674 case LIBSSH2_KNOWNHOST_KEY_ED25519:
675 hostkey_method = hostkey_method_ssh_ed25519;
676 break;
677 case LIBSSH2_KNOWNHOST_KEY_ECDSA_521:
678 hostkey_method = hostkey_method_ssh_ecdsa_521;
679 break;
680 case LIBSSH2_KNOWNHOST_KEY_ECDSA_384:
681 hostkey_method = hostkey_method_ssh_ecdsa_384;
682 break;
683 case LIBSSH2_KNOWNHOST_KEY_ECDSA_256:
684 hostkey_method = hostkey_method_ssh_ecdsa_256;
685 break;
686 case LIBSSH2_KNOWNHOST_KEY_SSHRSA:
687 hostkey_method = hostkey_method_ssh_rsa_all;
688 break;
689 case LIBSSH2_KNOWNHOST_KEY_SSHDSS:
690 hostkey_method = hostkey_method_ssh_dss;
691 break;
692 case LIBSSH2_KNOWNHOST_KEY_RSA1:
693 failf(data, "Found host key type RSA1 which is not supported");
694 return CURLE_SSH;
695 default:
696 failf(data, "Unknown host key type: %i",
697 (store->typemask & LIBSSH2_KNOWNHOST_KEY_MASK));
698 return CURLE_SSH;
699 }
700
701 infof(data, "Set \"%s\" as SSH hostkey type", hostkey_method);
702 rc = libssh2_session_method_pref(sshc->ssh_session,
703 LIBSSH2_METHOD_HOSTKEY, hostkey_method);
704 if(rc) {
705 char *err_msg = NULL;
706 int errlen;
707 libssh2_session_last_error(sshc->ssh_session, &err_msg, &errlen, 0);
708 failf(data, "libssh2 method '%s' failed: %s", hostkey_method, err_msg);
709 result = libssh2_session_error_to_CURLE(rc);
710 }
711 }
712 else {
713 infof(data, "Did not find host %s in %s",
714 conn->origin->hostname, data->set.str[STRING_SSH_KNOWNHOSTS]);
715 }
716 }
717
718 return result;
719}
720
721static CURLcode quote_error(struct Curl_easy *data,
722 struct ssh_conn *sshc)
723{
724 failf(data, "Suspicious data after the command line");
725 curlx_safefree(sshc->quote_path1);
726 curlx_safefree(sshc->quote_path2);
727 return CURLE_QUOTE_ERROR;
728}
729
730static CURLcode sftp_quote(struct Curl_easy *data,
731 struct ssh_conn *sshc,
732 struct SSHPROTO *sshp)
733{
734 const char *cp;
735 CURLcode result = CURLE_OK;
736
737 /*
738 * Support some of the "FTP" commands
739 *
740 * 'sshc->quote_item' is already verified to be non-NULL before it
741 * switched to this state.
742 */
743 const char *cmd = sshc->quote_item->data;
744 sshc->acceptfail = FALSE;
745
746 /* if a command starts with an asterisk, which a legal SFTP command never
747 can, the command is allowed to fail without it causing any
748 aborts or cancels etc. It causes libcurl to act as if the command
749 is successful, whatever the server responds. */
750
751 if(cmd[0] == '*') {
752 cmd++;
753 sshc->acceptfail = TRUE;
754 }
755
756 if(curl_strequal("pwd", cmd)) {
757 /* output debug output if that is requested */
758 char *tmp = curl_maprintf("257 \"%s\" is current directory.\n",
759 sshp->path);
760 if(!tmp)
761 return CURLE_OUT_OF_MEMORY;
762 Curl_debug(data, CURLINFO_HEADER_OUT, "PWD\n", 4);
763 Curl_debug(data, CURLINFO_HEADER_IN, tmp, strlen(tmp));
764
765 /* this sends an FTP-like "header" to the header callback so that
766 the current directory can be read similar to how it is read when
767 using ordinary FTP. */
768 result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
769 curlx_free(tmp);
770 if(!result)
771 myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
772 return result;
773 }
774
775 /*
776 * the arguments following the command must be separated from the
777 * command with a space so we can check for it unconditionally
778 */
779 cp = strchr(cmd, ' ');
780 if(!cp) {
781 failf(data, "Syntax error command '%s', missing parameter", cmd);
782 return result;
783 }
784
785 /*
786 * also, every command takes at least one argument so we get that
787 * first argument right now
788 */
789 result = Curl_get_pathname(&cp, &sshc->quote_path1, sshc->homedir);
790 if(result) {
791 if(result != CURLE_OUT_OF_MEMORY)
792 failf(data, "Syntax error: Bad first parameter to '%s'", cmd);
793 return result;
794 }
795
796 /*
797 * SFTP is a binary protocol, so we do not send text commands to the server.
798 * Instead, we scan for commands used by OpenSSH's sftp program and call the
799 * appropriate libssh2 functions.
800 */
801 if(!strncmp(cmd, "chgrp ", 6) ||
802 !strncmp(cmd, "chmod ", 6) ||
803 !strncmp(cmd, "chown ", 6) ||
804 !strncmp(cmd, "atime ", 6) ||
805 !strncmp(cmd, "mtime ", 6)) {
806 /* attribute change */
807
808 /* sshc->quote_path1 contains the mode to set */
809 /* get the destination */
810 result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
811 if(result) {
812 if(result != CURLE_OUT_OF_MEMORY)
813 failf(data, "Syntax error in %s: Bad second parameter", cmd);
814 curlx_safefree(sshc->quote_path1);
815 return result;
816 }
817 if(*cp)
818 return quote_error(data, sshc);
819
820 memset(&sshp->quote_attrs, 0, sizeof(LIBSSH2_SFTP_ATTRIBUTES));
821 myssh_to(data, sshc, SSH_SFTP_QUOTE_STAT);
822 return result;
823 }
824 if(!strncmp(cmd, "ln ", 3) ||
825 !strncmp(cmd, "symlink ", 8)) {
826 /* symbolic linking */
827 /* sshc->quote_path1 is the source */
828 /* get the destination */
829 result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
830 if(result) {
831 if(result != CURLE_OUT_OF_MEMORY)
832 failf(data, "Syntax error in ln/symlink: Bad second parameter");
833 curlx_safefree(sshc->quote_path1);
834 return result;
835 }
836 if(*cp)
837 return quote_error(data, sshc);
838 myssh_to(data, sshc, SSH_SFTP_QUOTE_SYMLINK);
839 return result;
840 }
841 else if(!strncmp(cmd, "mkdir ", 6)) {
842 if(*cp)
843 return quote_error(data, sshc);
844 /* create directory */
845 myssh_to(data, sshc, SSH_SFTP_QUOTE_MKDIR);
846 return result;
847 }
848 else if(!strncmp(cmd, "rename ", 7)) {
849 /* rename file */
850 /* first param is the source path */
851 /* second param is the dest. path */
852 result = Curl_get_pathname(&cp, &sshc->quote_path2, sshc->homedir);
853 if(result) {
854 if(result != CURLE_OUT_OF_MEMORY)
855 failf(data, "Syntax error in rename: Bad second parameter");
856 curlx_safefree(sshc->quote_path1);
857 return result;
858 }
859 if(*cp)
860 return quote_error(data, sshc);
861 myssh_to(data, sshc, SSH_SFTP_QUOTE_RENAME);
862 return result;
863 }
864 else if(!strncmp(cmd, "rmdir ", 6)) {
865 if(*cp)
866 return quote_error(data, sshc);
867 /* delete directory */
868 myssh_to(data, sshc, SSH_SFTP_QUOTE_RMDIR);
869 return result;
870 }
871 else if(!strncmp(cmd, "rm ", 3)) {
872 if(*cp)
873 return quote_error(data, sshc);
874 myssh_to(data, sshc, SSH_SFTP_QUOTE_UNLINK);
875 return result;
876 }
877 else if(!strncmp(cmd, "statvfs ", 8)) {
878 if(*cp)
879 return quote_error(data, sshc);
880 myssh_to(data, sshc, SSH_SFTP_QUOTE_STATVFS);
881 return result;
882 }
883
884 failf(data, "Unknown SFTP command");
885 curlx_safefree(sshc->quote_path1);
886 curlx_safefree(sshc->quote_path2);
887 return CURLE_QUOTE_ERROR;
888}
889
890static CURLcode sftp_upload_init(struct Curl_easy *data,
891 struct ssh_conn *sshc,
892 struct SSHPROTO *sshp,
893 bool *blockp)
894{
895 unsigned long flags;
896
897 /*
898 * NOTE!!! libssh2 requires that the destination path is a full path
899 * that includes the destination file and name OR ends in a "/"
900 * If this is not done the destination file is named the
901 * same name as the last directory in the path.
902 */
903
904 if(data->state.resume_from) {
905 LIBSSH2_SFTP_ATTRIBUTES attrs;
906 if(data->state.resume_from < 0) {
907 int rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path,
908 curlx_uztoui(strlen(sshp->path)),
909 LIBSSH2_SFTP_STAT, &attrs);
910 if(rc == LIBSSH2_ERROR_EAGAIN) {
911 *blockp = TRUE;
912 return CURLE_OK;
913 }
914 if(rc) {
915 data->state.resume_from = 0;
916 }
917 else {
918 curl_off_t size = attrs.filesize;
919 if(size < 0) {
920 failf(data, "Bad file size (%" FMT_OFF_T ")", size);
921 return CURLE_BAD_DOWNLOAD_RESUME;
922 }
923 data->state.resume_from = attrs.filesize;
924 }
925 }
926 }
927
928 if(data->set.remote_append) {
929 /* True append mode: create if nonexisting */
930 flags = LIBSSH2_FXF_WRITE | LIBSSH2_FXF_CREAT | LIBSSH2_FXF_APPEND;
931 }
932 else if(data->state.resume_from > 0) {
933 /*
934 * Resume MUST NOT use APPEND; some servers force writes to EOF when
935 * APPEND is set, ignoring a prior seek().
936 */
937 flags = LIBSSH2_FXF_WRITE;
938 }
939 else {
940 /* Clear file before writing (normal behavior) */
941 flags = LIBSSH2_FXF_WRITE | LIBSSH2_FXF_CREAT | LIBSSH2_FXF_TRUNC;
942 }
943
944 sshc->sftp_handle =
945 libssh2_sftp_open_ex(sshc->sftp_session, sshp->path,
946 curlx_uztoui(strlen(sshp->path)),
947 flags, (long)data->set.new_file_perms,
948 LIBSSH2_SFTP_OPENFILE);
949
950 if(!sshc->sftp_handle) {
951 CURLcode result;
952 unsigned long sftperr;
953 int rc = libssh2_session_last_errno(sshc->ssh_session);
954
955 if(LIBSSH2_ERROR_EAGAIN == rc) {
956 *blockp = TRUE;
957 return CURLE_OK;
958 }
959
960 if(LIBSSH2_ERROR_SFTP_PROTOCOL == rc)
961 /* only when there was an SFTP protocol error can we extract
962 the sftp error! */
963 sftperr = libssh2_sftp_last_error(sshc->sftp_session);
964 else
965 sftperr = LIBSSH2_FX_OK; /* not an sftp error at all */
966
967 if(sshc->secondCreateDirs) {
968 myssh_to(data, sshc, SSH_SFTP_CLOSE);
969 failf(data, "Creating the dir/file failed: %s",
970 sftp_libssh2_strerror(sftperr));
971 return sftp_libssh2_error_to_CURLE(sftperr);
972 }
973 if((sftperr == LIBSSH2_FX_NO_SUCH_FILE ||
974 sftperr == LIBSSH2_FX_FAILURE ||
975 sftperr == LIBSSH2_FX_NO_SUCH_PATH) &&
976 data->set.ftp_create_missing_dirs &&
977 (strlen(sshp->path) > 1)) {
978 /* try to create the path remotely */
979 sshc->secondCreateDirs = 1;
980 myssh_to(data, sshc, SSH_SFTP_CREATE_DIRS_INIT);
981 return CURLE_OK;
982 }
983 myssh_to(data, sshc, SSH_SFTP_CLOSE);
984 result = sftp_libssh2_error_to_CURLE(sftperr);
985 if(!result) {
986 /* Sometimes, for some reason libssh2_sftp_last_error() returns zero
987 even though libssh2_sftp_open() failed previously! We need to
988 work around that! */
989 result = CURLE_SSH;
990 sftperr = LIBSSH2_FX_OK;
991 }
992 failf(data, "Upload failed: %s (%lu/%d)",
993 sftperr != LIBSSH2_FX_OK ?
994 sftp_libssh2_strerror(sftperr) : "ssh error",
995 sftperr, rc);
996 return result;
997 }
998
999 /* If we have a restart point then we need to seek to the correct
1000 Skip if in explicit remote append mode. */
1001 if(data->state.resume_from > 0 && !data->set.remote_append) {
1002 int seekerr = CURL_SEEKFUNC_OK;
1003 /* Let's read off the proper amount of bytes from the input. */
1004 if(data->set.seek_func) {
1005 Curl_set_in_callback(data, TRUE);
1006 seekerr = data->set.seek_func(data->set.seek_client,
1007 data->state.resume_from, SEEK_SET);
1008 Curl_set_in_callback(data, FALSE);
1009 }
1010
1011 if(seekerr != CURL_SEEKFUNC_OK) {
1012 curl_off_t passed = 0;
1013
1014 if(seekerr != CURL_SEEKFUNC_CANTSEEK) {
1015 failf(data, "Could not seek stream");
1016 return CURLE_FTP_COULDNT_USE_REST;
1017 }
1018 /* seekerr == CURL_SEEKFUNC_CANTSEEK (cannot seek to offset) */
1019 do {
1020 char scratch[4 * 1024];
1021 size_t readthisamountnow =
1022 (data->state.resume_from - passed >
1023 (curl_off_t)sizeof(scratch)) ?
1024 sizeof(scratch) : curlx_sotouz(data->state.resume_from - passed);
1025
1026 size_t actuallyread;
1027 Curl_set_in_callback(data, TRUE);
1028 actuallyread = data->state.fread_func(scratch, 1,
1029 readthisamountnow,
1030 data->state.in);
1031 Curl_set_in_callback(data, FALSE);
1032
1033 passed += actuallyread;
1034 if((actuallyread == 0) || (actuallyread > readthisamountnow)) {
1035 /* this checks for greater-than only to make sure that the
1036 CURL_READFUNC_ABORT return code still aborts */
1037 failf(data, "Failed to read data");
1038 return CURLE_FTP_COULDNT_USE_REST;
1039 }
1040 } while(passed < data->state.resume_from);
1041 }
1042
1043 /* now, decrease the size of the read */
1044 if(data->state.infilesize > 0) {
1045 data->state.infilesize -= data->state.resume_from;
1046 data->req.size = data->state.infilesize;
1047 Curl_pgrsSetUploadSize(data, data->state.infilesize);
1048 }
1049
1050 libssh2_sftp_seek64(sshc->sftp_handle,
1051 (libssh2_uint64_t)data->state.resume_from);
1052 }
1053 if(data->state.infilesize > 0) {
1054 data->req.size = data->state.infilesize;
1055 Curl_pgrsSetUploadSize(data, data->state.infilesize);
1056 }
1057 /* upload data */
1058 Curl_xfer_setup_send(data, FIRSTSOCKET);
1059
1060 /* not set by Curl_xfer_setup to preserve io_flags */
1061 data->conn->recv_idx = FIRSTSOCKET;
1062
1063 /* since we do not really wait for anything at this point, we want the
1064 state machine to move on as soon as possible so mark this as dirty */
1065 Curl_multi_mark_dirty(data);
1066
1067 myssh_to(data, sshc, SSH_STOP);
1068 return CURLE_OK;
1069}
1070
1071static CURLcode ssh_state_pkey_init(struct Curl_easy *data,
1072 struct ssh_conn *sshc)
1073{
1074 /*
1075 * Check the supported auth types in the order I feel is most secure
1076 * with the requested type of authentication
1077 */
1078 sshc->authed = FALSE;
1079
1080 if((data->set.ssh_auth_types & CURLSSH_AUTH_PUBLICKEY) &&
1081 (strstr(sshc->authlist, "publickey") != NULL)) {
1082 bool out_of_memory = FALSE;
1083
1084 sshc->rsa_pub = sshc->rsa = NULL;
1085
1086 if(data->set.str[STRING_SSH_PRIVATE_KEY]) {
1087 sshc->rsa = curlx_strdup(data->set.str[STRING_SSH_PRIVATE_KEY]);
1088 if(!sshc->rsa)
1089 out_of_memory = TRUE;
1090 }
1091 else {
1092 /* To ponder about: should really the lib be messing about with the
1093 HOME environment variable etc? */
1094 char *home = curl_getenv("HOME");
1095 curlx_struct_stat sbuf;
1096
1097 /* If no private key file is specified, try some common paths. */
1098 if(home) {
1099 /* Try ~/.ssh first. */
1100 sshc->rsa = curl_maprintf("%s/.ssh/id_rsa", home);
1101 if(!sshc->rsa)
1102 out_of_memory = TRUE;
1103 else if(curlx_stat(sshc->rsa, &sbuf)) {
1104 curlx_free(sshc->rsa);
1105 sshc->rsa = curl_maprintf("%s/.ssh/id_dsa", home);
1106 if(!sshc->rsa)
1107 out_of_memory = TRUE;
1108 else if(curlx_stat(sshc->rsa, &sbuf)) {
1109 curlx_safefree(sshc->rsa);
1110 }
1111 }
1112 curlx_free(home);
1113 }
1114 if(!out_of_memory && !sshc->rsa) {
1115 /* Nothing found; try the current dir. */
1116 sshc->rsa = curlx_strdup("id_rsa");
1117 if(sshc->rsa && curlx_stat(sshc->rsa, &sbuf)) {
1118 curlx_free(sshc->rsa);
1119 sshc->rsa = curlx_strdup("id_dsa");
1120 if(sshc->rsa && curlx_stat(sshc->rsa, &sbuf)) {
1121 curlx_free(sshc->rsa);
1122 /* Out of guesses. Set to the empty string to avoid
1123 * surprising info messages. */
1124 sshc->rsa = curlx_strdup("");
1125 }
1126 }
1127 }
1128 }
1129
1130 /*
1131 * Unless the user explicitly specifies a public key file, let
1132 * libssh2 extract the public key from the private key file.
1133 * This is done by passing sshc->rsa_pub = NULL.
1134 */
1135 if(!out_of_memory && data->set.str[STRING_SSH_PUBLIC_KEY] &&
1136 /* treat empty string the same way as NULL */
1137 data->set.str[STRING_SSH_PUBLIC_KEY][0]) {
1138 sshc->rsa_pub = curlx_strdup(data->set.str[STRING_SSH_PUBLIC_KEY]);
1139 if(!sshc->rsa_pub)
1140 out_of_memory = TRUE;
1141 }
1142
1143 if(out_of_memory || !sshc->rsa) {
1144 curlx_safefree(sshc->rsa);
1145 curlx_safefree(sshc->rsa_pub);
1146 myssh_to(data, sshc, SSH_SESSION_FREE);
1147 return CURLE_OUT_OF_MEMORY;
1148 }
1149
1150 sshc->passphrase = data->set.ssl.key_passwd;
1151 if(!sshc->passphrase)
1152 sshc->passphrase = "";
1153
1154 if(sshc->rsa_pub)
1155 infof(data, "Using SSH public key file '%s'", sshc->rsa_pub);
1156 infof(data, "Using SSH private key file '%s'", sshc->rsa);
1157
1158 myssh_to(data, sshc, SSH_AUTH_PKEY);
1159 }
1160 else {
1161 myssh_to(data, sshc, SSH_AUTH_PASS_INIT);
1162 }
1163 return CURLE_OK;
1164}
1165
1166static CURLcode sftp_quote_stat(struct Curl_easy *data,
1167 struct ssh_conn *sshc,
1168 struct SSHPROTO *sshp,
1169 bool *blockp)
1170{
1171 const char *cmd = sshc->quote_item->data;
1172 sshc->acceptfail = FALSE;
1173
1174 /* if a command starts with an asterisk, which a legal SFTP command never
1175 can, the command is allowed to fail without it causing any aborts or
1176 cancels etc. It causes libcurl to act as if the command is
1177 successful, whatever the server responds. */
1178
1179 if(cmd[0] == '*') {
1180 cmd++;
1181 sshc->acceptfail = TRUE;
1182 }
1183
1184 if(!!strncmp(cmd, "chmod", 5)) {
1185 /* Since chown and chgrp only set owner OR group but libssh2 wants to set
1186 * them both at once, we need to obtain the current ownership first. This
1187 * takes an extra protocol round trip.
1188 */
1189 int rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2,
1190 curlx_uztoui(strlen(sshc->quote_path2)),
1191 LIBSSH2_SFTP_STAT,
1192 &sshp->quote_attrs);
1193 if(rc == LIBSSH2_ERROR_EAGAIN) {
1194 *blockp = TRUE;
1195 return CURLE_OK;
1196 }
1197 if(rc && !sshc->acceptfail) { /* get those attributes */
1198 unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
1199 failf(data, "Attempt to get SFTP stats failed: %s",
1200 sftp_libssh2_strerror(sftperr));
1201 goto fail;
1202 }
1203 }
1204
1205 /* Now set the new attributes... */
1206 if(!strncmp(cmd, "chgrp", 5)) {
1207 const char *p = sshc->quote_path1;
1208 curl_off_t gid;
1209 if(!curlx_str_number(&p, &gid, ULONG_MAX)) {
1210 sshp->quote_attrs.gid = (unsigned long)gid;
1211 sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
1212 }
1213 else if(!sshc->acceptfail) {
1214 failf(data, "Syntax error: chgrp gid not a number");
1215 goto fail;
1216 }
1217 }
1218 else if(!strncmp(cmd, "chmod", 5)) {
1219 curl_off_t perms;
1220 const char *p = sshc->quote_path1;
1221 /* permissions are octal */
1222 if(curlx_str_octal(&p, &perms, 07777)) {
1223 failf(data, "Syntax error: chmod permissions not a number");
1224 goto fail;
1225 }
1226
1227 sshp->quote_attrs.permissions = (unsigned long)perms;
1228 sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_PERMISSIONS;
1229 }
1230 else if(!strncmp(cmd, "chown", 5)) {
1231 const char *p = sshc->quote_path1;
1232 curl_off_t uid;
1233 if(!curlx_str_number(&p, &uid, ULONG_MAX)) {
1234 sshp->quote_attrs.uid = (unsigned long)uid;
1235 sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_UIDGID;
1236 }
1237 else if(!sshc->acceptfail) {
1238 failf(data, "Syntax error: chown uid not a number");
1239 goto fail;
1240 }
1241 }
1242 else if(!strncmp(cmd, "atime", 5) ||
1243 !strncmp(cmd, "mtime", 5)) {
1244 time_t date;
1245 bool fail = FALSE;
1246
1247 if(Curl_getdate_capped(sshc->quote_path1, &date)) {
1248 failf(data, "incorrect date format for %.*s", 5, cmd);
1249 fail = TRUE;
1250 }
1251#if SIZEOF_TIME_T > SIZEOF_LONG
1252 if(date > 0xffffffff) {
1253 /* if 'long' cannot hold >32-bit, this date cannot be sent */
1254 failf(data, "date overflow");
1255 fail = TRUE;
1256 }
1257#endif
1258 if(fail)
1259 goto fail;
1260 if(!strncmp(cmd, "atime", 5))
1261 sshp->quote_attrs.atime = (unsigned long)date;
1262 else /* mtime */
1263 sshp->quote_attrs.mtime = (unsigned long)date;
1264
1265 sshp->quote_attrs.flags = LIBSSH2_SFTP_ATTR_ACMODTIME;
1266 }
1267
1268 /* Now send the completed structure... */
1269 myssh_to(data, sshc, SSH_SFTP_QUOTE_SETSTAT);
1270 return CURLE_OK;
1271fail:
1272 curlx_safefree(sshc->quote_path1);
1273 curlx_safefree(sshc->quote_path2);
1274 return CURLE_QUOTE_ERROR;
1275}
1276
1277static CURLcode sftp_download_stat(struct Curl_easy *data,
1278 struct ssh_conn *sshc,
1279 struct SSHPROTO *sshp,
1280 bool *blockp)
1281{
1282 LIBSSH2_SFTP_ATTRIBUTES attrs;
1283 int rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path,
1284 curlx_uztoui(strlen(sshp->path)),
1285 LIBSSH2_SFTP_STAT, &attrs);
1286 if(rc == LIBSSH2_ERROR_EAGAIN) {
1287 *blockp = TRUE;
1288 return CURLE_OK;
1289 }
1290 if(rc ||
1291 !(attrs.flags & LIBSSH2_SFTP_ATTR_SIZE) ||
1292 (attrs.filesize == 0)) {
1293 /*
1294 * libssh2_sftp_open() did not return an error, so maybe the server
1295 * does not support stat()
1296 * OR the server does not return a file size with a stat()
1297 * OR file size is 0
1298 */
1299 data->req.size = -1;
1300 data->req.maxdownload = -1;
1301 Curl_pgrsSetDownloadSize(data, -1);
1302 attrs.filesize = 0; /* might be uninitialized but is read below */
1303 }
1304 else {
1305 curl_off_t size = attrs.filesize;
1306
1307 if(size < 0) {
1308 failf(data, "Bad file size (%" FMT_OFF_T ")", size);
1309 return CURLE_BAD_DOWNLOAD_RESUME;
1310 }
1311 if(data->state.use_range) {
1312 curl_off_t from;
1313 CURLcode result = Curl_ssh_range(data, data->state.range, size,
1314 &from, &size);
1315 if(result)
1316 return result;
1317
1318 libssh2_sftp_seek64(sshc->sftp_handle, (libssh2_uint64_t)from);
1319 }
1320 data->req.size = size;
1321 data->req.maxdownload = size;
1322 Curl_pgrsSetDownloadSize(data, size);
1323 }
1324
1325 /* We can resume if we can seek to the resume position */
1326 if(data->state.resume_from) {
1327 if(data->state.resume_from < 0) {
1328 /* We are supposed to download the last abs(from) bytes */
1329 if((curl_off_t)attrs.filesize < -data->state.resume_from) {
1330 failf(data, "Offset (%" FMT_OFF_T ") was beyond file size (%"
1331 FMT_OFF_T ")",
1332 data->state.resume_from, (curl_off_t)attrs.filesize);
1333 return CURLE_BAD_DOWNLOAD_RESUME;
1334 }
1335 /* download from where? */
1336 data->state.resume_from += attrs.filesize;
1337 }
1338 else {
1339 if((curl_off_t)attrs.filesize < data->state.resume_from) {
1340 failf(data, "Offset (%" FMT_OFF_T
1341 ") was beyond file size (%" FMT_OFF_T ")",
1342 data->state.resume_from, (curl_off_t)attrs.filesize);
1343 return CURLE_BAD_DOWNLOAD_RESUME;
1344 }
1345 }
1346 /* Now store the number of bytes we are expected to download */
1347 data->req.size = attrs.filesize - data->state.resume_from;
1348 data->req.maxdownload = attrs.filesize - data->state.resume_from;
1349 Curl_pgrsSetDownloadSize(data, attrs.filesize - data->state.resume_from);
1350 libssh2_sftp_seek64(sshc->sftp_handle,
1351 (libssh2_uint64_t)data->state.resume_from);
1352 }
1353
1354 /* Setup the actual download */
1355 if(data->req.size == 0) {
1356 /* no data to transfer */
1357 Curl_xfer_setup_nop(data);
1358 infof(data, "File already completely downloaded");
1359 myssh_to(data, sshc, SSH_STOP);
1360 return CURLE_OK;
1361 }
1362 Curl_xfer_setup_recv(data, FIRSTSOCKET, data->req.size);
1363
1364 /* not set by Curl_xfer_setup to preserve io_flags */
1365 data->conn->send_idx = 0;
1366
1367 myssh_to(data, sshc, SSH_STOP);
1368
1369 return CURLE_OK;
1370}
1371
1372static CURLcode sftp_readdir(struct Curl_easy *data,
1373 struct ssh_conn *sshc,
1374 struct SSHPROTO *sshp,
1375 bool *blockp)
1376{
1377 CURLcode result = CURLE_OK;
1378 int rc = libssh2_sftp_readdir_ex(sshc->sftp_handle,
1379 sshp->readdir_filename, CURL_PATH_MAX,
1380 sshp->readdir_longentry, CURL_PATH_MAX,
1381 &sshp->readdir_attrs);
1382 if(rc == LIBSSH2_ERROR_EAGAIN) {
1383 *blockp = TRUE;
1384 return result;
1385 }
1386 if(rc > 0) {
1387 size_t readdir_len = (size_t)rc;
1388 sshp->readdir_filename[readdir_len] = '\0';
1389
1390 if(data->set.list_only) {
1391 result = Curl_client_write(data, CLIENTWRITE_BODY,
1392 sshp->readdir_filename,
1393 readdir_len);
1394 if(!result)
1395 result = Curl_client_write(data, CLIENTWRITE_BODY, "\n", 1);
1396 if(result)
1397 return result;
1398 }
1399 else {
1400 result = curlx_dyn_add(&sshp->readdir, sshp->readdir_longentry);
1401
1402 if(!result) {
1403 if((sshp->readdir_attrs.flags & LIBSSH2_SFTP_ATTR_PERMISSIONS) &&
1404 ((sshp->readdir_attrs.permissions & LIBSSH2_SFTP_S_IFMT) ==
1405 LIBSSH2_SFTP_S_IFLNK)) {
1406 result = curlx_dyn_addf(&sshp->readdir_link, "%s%s", sshp->path,
1407 sshp->readdir_filename);
1408 myssh_to(data, sshc, SSH_SFTP_READDIR_LINK);
1409 }
1410 else {
1411 myssh_to(data, sshc, SSH_SFTP_READDIR_BOTTOM);
1412 }
1413 }
1414 return result;
1415 }
1416 }
1417 else if(!rc) {
1418 myssh_to(data, sshc, SSH_SFTP_READDIR_DONE);
1419 }
1420 else {
1421 unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
1422 result = sftperr ? sftp_libssh2_error_to_CURLE(sftperr) : CURLE_SSH;
1423 failf(data, "Could not open remote file for reading: %s :: %d",
1424 sftp_libssh2_strerror(sftperr),
1425 libssh2_session_last_errno(sshc->ssh_session));
1426 myssh_to(data, sshc, SSH_SFTP_CLOSE);
1427 }
1428 return result;
1429}
1430
1431static CURLcode ssh_state_init(struct Curl_easy *data,
1432 struct ssh_conn *sshc)
1433{
1434 CURLcode result;
1435 sshc->secondCreateDirs = 0;
1436 sshc->nextstate = SSH_NO_STATE;
1437
1438 /* Set libssh2 to non-blocking, since everything internally is
1439 non-blocking */
1440 libssh2_session_set_blocking(sshc->ssh_session, 0);
1441
1442 result = ssh_force_knownhost_key_type(data, sshc);
1443 if(result)
1444 myssh_to(data, sshc, SSH_SESSION_FREE);
1445 else
1446 myssh_to(data, sshc, SSH_S_STARTUP);
1447 return result;
1448}
1449
1450static CURLcode ssh_state_startup(struct Curl_easy *data,
1451 struct ssh_conn *sshc)
1452{
1453 struct connectdata *conn = data->conn;
1454 int rc = libssh2_session_handshake(sshc->ssh_session,
1455 conn->sock[FIRSTSOCKET]);
1456 if(rc == LIBSSH2_ERROR_EAGAIN)
1457 return CURLE_AGAIN;
1458
1459 if(rc) {
1460 char *err_msg = NULL;
1461 (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0);
1462 failf(data, "Failure establishing ssh session: %d, %s", rc, err_msg);
1463
1464 myssh_to(data, sshc, SSH_SESSION_FREE);
1465 return CURLE_FAILED_INIT;
1466 }
1467
1468 myssh_to(data, sshc, SSH_HOSTKEY);
1469 return CURLE_OK;
1470}
1471
1472static CURLcode ssh_state_hostkey(struct Curl_easy *data,
1473 struct ssh_conn *sshc)
1474{
1475 /*
1476 * Before we authenticate we should check the hostkey's fingerprint
1477 * against our known hosts. How that is handled (reading from file,
1478 * whatever) is up to us.
1479 */
1480 CURLcode result = ssh_check_fingerprint(data, sshc);
1481 if(!result)
1482 myssh_to(data, sshc, SSH_AUTHLIST);
1483 return result;
1484}
1485
1486static CURLcode ssh_state_authlist(struct Curl_easy *data,
1487 struct ssh_conn *sshc)
1488{
1489 /*
1490 * Figure out authentication methods
1491 * NB: As soon as we have provided a username to an openssh server we
1492 * must never change it later. Thus, always specify the correct username
1493 * here, even though the libssh2 docs kind of indicate that it should be
1494 * possible to get a 'generic' list (not user-specific) of authentication
1495 * methods, presumably with a blank username. That does not work in my
1496 * experience.
1497 * Therefore always specify it here.
1498 */
1499 struct connectdata *conn = data->conn;
1500 const char *user = Curl_creds_user(conn->creds);
1501 sshc->authlist = libssh2_userauth_list(sshc->ssh_session,
1502 user, curlx_uztoui(strlen(user)));
1503
1504 if(!sshc->authlist) {
1505 int rc;
1506 if(libssh2_userauth_authenticated(sshc->ssh_session)) {
1507 sshc->authed = TRUE;
1508 infof(data, "SSH user accepted with no authentication");
1509 myssh_to(data, sshc, SSH_AUTH_DONE);
1510 return CURLE_OK;
1511 }
1512 rc = libssh2_session_last_errno(sshc->ssh_session);
1513 if(rc == LIBSSH2_ERROR_EAGAIN)
1514 return CURLE_AGAIN;
1515
1516 myssh_to(data, sshc, SSH_SESSION_FREE);
1517 return libssh2_session_error_to_CURLE(rc);
1518 }
1519 infof(data, "SSH authentication methods available: %s", sshc->authlist);
1520
1521 myssh_to(data, sshc, SSH_AUTH_PKEY_INIT);
1522 return CURLE_OK;
1523}
1524
1525static CURLcode ssh_state_auth_pkey(struct Curl_easy *data,
1526 struct ssh_conn *sshc)
1527{
1528 /* The function below checks if the files exists, no need to stat() here.
1529 */
1530 struct connectdata *conn = data->conn;
1531 const char *user = Curl_creds_user(conn->creds);
1532 int rc =
1533 libssh2_userauth_publickey_fromfile_ex(sshc->ssh_session,
1534 user,
1535 curlx_uztoui(strlen(user)),
1536 sshc->rsa_pub,
1537 sshc->rsa, sshc->passphrase);
1538 if(rc == LIBSSH2_ERROR_EAGAIN)
1539 return CURLE_AGAIN;
1540
1541 curlx_safefree(sshc->rsa_pub);
1542 curlx_safefree(sshc->rsa);
1543
1544 if(rc == 0) {
1545 sshc->authed = TRUE;
1546 infof(data, "Initialized SSH public key authentication");
1547 myssh_to(data, sshc, SSH_AUTH_DONE);
1548 }
1549 else {
1550 char *err_msg = NULL;
1551 char unknown[] = "Reason unknown (-1)";
1552 if(rc == -1) {
1553 /* No error message has been set and the last set error message, if
1554 any, is from a previous error so ignore it. #11837 */
1555 err_msg = unknown;
1556 }
1557 else {
1558 (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0);
1559 }
1560 infof(data, "SSH public key authentication failed: %s", err_msg);
1561 myssh_to(data, sshc, SSH_AUTH_PASS_INIT);
1562 }
1563 return CURLE_OK;
1564}
1565
1566static CURLcode ssh_state_auth_pass_init(struct Curl_easy *data,
1567 struct ssh_conn *sshc)
1568{
1569 if((data->set.ssh_auth_types & CURLSSH_AUTH_PASSWORD) &&
1570 (strstr(sshc->authlist, "password") != NULL)) {
1571 myssh_to(data, sshc, SSH_AUTH_PASS);
1572 }
1573 else {
1574 myssh_to(data, sshc, SSH_AUTH_HOST_INIT);
1575 }
1576 return CURLE_OK;
1577}
1578
1579static CURLcode ssh_state_auth_pass(struct Curl_easy *data,
1580 struct ssh_conn *sshc)
1581{
1582 struct connectdata *conn = data->conn;
1583 const char *user = Curl_creds_user(conn->creds);
1584 const char *passwd = Curl_creds_passwd(conn->creds);
1585 int rc =
1586 libssh2_userauth_password_ex(sshc->ssh_session, user,
1587 curlx_uztoui(strlen(user)),
1588 passwd,
1589 curlx_uztoui(strlen(passwd)),
1590 NULL);
1591 if(rc == LIBSSH2_ERROR_EAGAIN) {
1592 return CURLE_AGAIN;
1593 }
1594 if(rc == 0) {
1595 sshc->authed = TRUE;
1596 infof(data, "Initialized password authentication");
1597 myssh_to(data, sshc, SSH_AUTH_DONE);
1598 }
1599 else {
1600 myssh_to(data, sshc, SSH_AUTH_HOST_INIT);
1601 }
1602 return CURLE_OK;
1603}
1604
1605static CURLcode ssh_state_auth_host_init(struct Curl_easy *data,
1606 struct ssh_conn *sshc)
1607{
1608 if((data->set.ssh_auth_types & CURLSSH_AUTH_HOST) &&
1609 (strstr(sshc->authlist, "hostbased") != NULL)) {
1610 myssh_to(data, sshc, SSH_AUTH_HOST);
1611 }
1612 else {
1613 myssh_to(data, sshc, SSH_AUTH_AGENT_INIT);
1614 }
1615 return CURLE_OK;
1616}
1617
1618static CURLcode ssh_state_auth_agent_init(struct Curl_easy *data,
1619 struct ssh_conn *sshc)
1620{
1621 int rc = 0;
1622 if((data->set.ssh_auth_types & CURLSSH_AUTH_AGENT) &&
1623 (strstr(sshc->authlist, "publickey") != NULL)) {
1624
1625 /* Connect to the ssh-agent */
1626 /* The agent could be shared by a curl thread i believe
1627 but nothing obvious as keys can be added/removed at any time */
1628 if(!sshc->ssh_agent) {
1629 sshc->ssh_agent = libssh2_agent_init(sshc->ssh_session);
1630 if(!sshc->ssh_agent) {
1631 infof(data, "Could not create agent object");
1632
1633 myssh_to(data, sshc, SSH_AUTH_KEY_INIT);
1634 return CURLE_OK;
1635 }
1636 }
1637
1638 rc = libssh2_agent_connect(sshc->ssh_agent);
1639 if(rc == LIBSSH2_ERROR_EAGAIN)
1640 return CURLE_AGAIN;
1641 if(rc < 0) {
1642 infof(data, "Failure connecting to agent");
1643 myssh_to(data, sshc, SSH_AUTH_KEY_INIT);
1644 }
1645 else {
1646 myssh_to(data, sshc, SSH_AUTH_AGENT_LIST);
1647 }
1648 }
1649 else
1650 myssh_to(data, sshc, SSH_AUTH_KEY_INIT);
1651 return CURLE_OK;
1652}
1653
1654static CURLcode ssh_state_auth_agent_list(struct Curl_easy *data,
1655 struct ssh_conn *sshc)
1656{
1657 int rc = libssh2_agent_list_identities(sshc->ssh_agent);
1658
1659 if(rc == LIBSSH2_ERROR_EAGAIN)
1660 return CURLE_AGAIN;
1661 if(rc < 0) {
1662 infof(data, "Failure requesting identities to agent");
1663 myssh_to(data, sshc, SSH_AUTH_KEY_INIT);
1664 }
1665 else {
1666 myssh_to(data, sshc, SSH_AUTH_AGENT);
1667 sshc->sshagent_prev_identity = NULL;
1668 }
1669 return CURLE_OK;
1670}
1671
1672static CURLcode ssh_state_auth_agent(struct Curl_easy *data,
1673 struct ssh_conn *sshc)
1674{
1675 /* as prev_identity evolves only after an identity user auth finished we
1676 can safely request it again as long as EAGAIN is returned here or by
1677 libssh2_agent_userauth */
1678 int rc = libssh2_agent_get_identity(sshc->ssh_agent,
1679 &sshc->sshagent_identity,
1680 sshc->sshagent_prev_identity);
1681 if(rc == LIBSSH2_ERROR_EAGAIN)
1682 return CURLE_AGAIN;
1683
1684 if(rc == 0) {
1685 struct connectdata *conn = data->conn;
1686 rc = libssh2_agent_userauth(sshc->ssh_agent, Curl_creds_user(conn->creds),
1687 sshc->sshagent_identity);
1688
1689 if(rc < 0) {
1690 if(rc != LIBSSH2_ERROR_EAGAIN) {
1691 /* tried and failed? go to next identity */
1692 sshc->sshagent_prev_identity = sshc->sshagent_identity;
1693 return CURLE_OK;
1694 }
1695 return CURLE_AGAIN;
1696 }
1697 }
1698
1699 if(rc < 0)
1700 infof(data, "Failure requesting identities to agent");
1701 else if(rc == 1)
1702 infof(data, "No identity would match");
1703
1704 if(rc == LIBSSH2_ERROR_NONE) {
1705 sshc->authed = TRUE;
1706 infof(data, "Agent based authentication successful");
1707 myssh_to(data, sshc, SSH_AUTH_DONE);
1708 }
1709 else {
1710 myssh_to(data, sshc, SSH_AUTH_KEY_INIT);
1711 }
1712 return CURLE_OK;
1713}
1714
1715static CURLcode ssh_state_auth_key_init(struct Curl_easy *data,
1716 struct ssh_conn *sshc)
1717{
1718 if((data->set.ssh_auth_types & CURLSSH_AUTH_KEYBOARD) &&
1719 (strstr(sshc->authlist, "keyboard-interactive") != NULL)) {
1720 myssh_to(data, sshc, SSH_AUTH_KEY);
1721 }
1722 else {
1723 myssh_to(data, sshc, SSH_AUTH_DONE);
1724 }
1725 return CURLE_OK;
1726}
1727
1728static CURLcode ssh_state_auth_key(struct Curl_easy *data,
1729 struct ssh_conn *sshc)
1730{
1731 /* Authentication failed. Continue with keyboard-interactive now. */
1732 struct connectdata *conn = data->conn;
1733 const char *user = Curl_creds_user(conn->creds);
1734 int rc =
1735 libssh2_userauth_keyboard_interactive_ex(sshc->ssh_session,
1736 user, curlx_uztoui(strlen(user)),
1737 &kbd_callback);
1738 if(rc == LIBSSH2_ERROR_EAGAIN)
1739 return CURLE_AGAIN;
1740
1741 if(rc == 0) {
1742 sshc->authed = TRUE;
1743 infof(data, "Initialized keyboard interactive authentication");
1744 myssh_to(data, sshc, SSH_AUTH_DONE);
1745 return CURLE_OK;
1746 }
1747 return CURLE_LOGIN_DENIED;
1748}
1749
1750static CURLcode ssh_state_auth_done(struct Curl_easy *data,
1751 struct ssh_conn *sshc)
1752{
1753 struct connectdata *conn = data->conn;
1754 if(!sshc->authed) {
1755 failf(data, "Authentication failure");
1756 myssh_to(data, sshc, SSH_SESSION_FREE);
1757 return CURLE_LOGIN_DENIED;
1758 }
1759
1760 /*
1761 * At this point we have an authenticated ssh session.
1762 */
1763 infof(data, "Authentication complete");
1764
1765 Curl_pgrsTime(data, TIMER_APPCONNECT); /* SSH is connected */
1766
1767 data->conn->recv_idx = FIRSTSOCKET;
1768 conn->send_idx = -1;
1769
1770 if(conn->scheme->protocol == CURLPROTO_SFTP) {
1771 myssh_to(data, sshc, SSH_SFTP_INIT);
1772 return CURLE_OK;
1773 }
1774 infof(data, "SSH CONNECT phase done");
1775 myssh_to(data, sshc, SSH_STOP);
1776 return CURLE_OK;
1777}
1778
1779static CURLcode ssh_state_sftp_init(struct Curl_easy *data,
1780 struct ssh_conn *sshc)
1781{
1782 /*
1783 * Start the libssh2 sftp session
1784 */
1785 sshc->sftp_session = libssh2_sftp_init(sshc->ssh_session);
1786 if(!sshc->sftp_session) {
1787 char *err_msg = NULL;
1788 if(libssh2_session_last_errno(sshc->ssh_session) ==
1789 LIBSSH2_ERROR_EAGAIN)
1790 return CURLE_AGAIN;
1791
1792 (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0);
1793 failf(data, "Failure initializing sftp session: %s", err_msg);
1794 myssh_to(data, sshc, SSH_SESSION_FREE);
1795 return CURLE_FAILED_INIT;
1796 }
1797 myssh_to(data, sshc, SSH_SFTP_REALPATH);
1798 return CURLE_OK;
1799}
1800
1801static CURLcode ssh_state_sftp_realpath(struct Curl_easy *data,
1802 struct ssh_conn *sshc,
1803 struct SSHPROTO *sshp)
1804{
1805 /*
1806 * Get the "home" directory
1807 */
1808 int rc;
1809
1810 if(!sshp)
1811 return CURLE_FAILED_INIT;
1812
1813 rc = libssh2_sftp_symlink_ex(sshc->sftp_session, ".",
1814 curlx_uztoui(strlen(".")),
1815 sshp->readdir_filename, CURL_PATH_MAX,
1816 LIBSSH2_SFTP_REALPATH);
1817 if(rc == LIBSSH2_ERROR_EAGAIN)
1818 return CURLE_AGAIN;
1819
1820 myssh_to(data, sshc, SSH_STOP);
1821 if(rc > 0) {
1822 curlx_free(sshc->homedir);
1823 sshc->homedir = curlx_strdup(sshp->readdir_filename);
1824 if(!sshc->homedir)
1825 return CURLE_OUT_OF_MEMORY;
1826 curlx_free(data->state.most_recent_ftp_entrypath);
1827 data->state.most_recent_ftp_entrypath = curlx_strdup(sshc->homedir);
1828 if(!data->state.most_recent_ftp_entrypath)
1829 return CURLE_OUT_OF_MEMORY;
1830 }
1831 else {
1832 /* Return the error type */
1833 unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
1834 CURLcode result;
1835 if(sftperr)
1836 result = sftp_libssh2_error_to_CURLE(sftperr);
1837 else
1838 /* in this case, the error was not in the SFTP level but for example a
1839 time-out or similar */
1840 result = CURLE_SSH;
1841 CURL_TRC_SSH(data, "error = %lu makes libcurl = %d", sftperr, (int)result);
1842 return result;
1843 }
1844
1845 /* This is the last step in the SFTP connect phase. Do note that while we
1846 get the homedir here, we get the "workingpath" in the DO action since the
1847 homedir remains the same between request but the working path does not. */
1848 CURL_TRC_SSH(data, "CONNECT phase done");
1849 return CURLE_OK;
1850}
1851
1852static CURLcode ssh_state_sftp_quote_init(struct Curl_easy *data,
1853 struct ssh_conn *sshc,
1854 struct SSHPROTO *sshp)
1855{
1856 CURLcode result;
1857
1858 if(!sshp)
1859 return CURLE_FAILED_INIT;
1860
1861 result = Curl_getworkingpath(data, sshc->homedir, &sshp->path);
1862 if(result) {
1863 myssh_to(data, sshc, SSH_STOP);
1864 return result;
1865 }
1866
1867 if(data->set.quote) {
1868 infof(data, "Sending quote commands");
1869 sshc->quote_item = data->set.quote;
1870 myssh_to(data, sshc, SSH_SFTP_QUOTE);
1871 }
1872 else {
1873 myssh_to(data, sshc, SSH_SFTP_GETINFO);
1874 }
1875 return CURLE_OK;
1876}
1877
1878static CURLcode ssh_state_sftp_postquote_init(struct Curl_easy *data,
1879 struct ssh_conn *sshc)
1880{
1881 if(data->set.postquote) {
1882 infof(data, "Sending quote commands");
1883 sshc->quote_item = data->set.postquote;
1884 myssh_to(data, sshc, SSH_SFTP_QUOTE);
1885 }
1886 else {
1887 myssh_to(data, sshc, SSH_STOP);
1888 }
1889 return CURLE_OK;
1890}
1891
1892static CURLcode ssh_state_sftp_quote(struct Curl_easy *data,
1893 struct ssh_conn *sshc,
1894 struct SSHPROTO *sshp)
1895{
1896 /* Send quote commands */
1897 CURLcode result;
1898
1899 if(!sshp)
1900 return CURLE_FAILED_INIT;
1901
1902 result = sftp_quote(data, sshc, sshp);
1903 if(result) {
1904 myssh_to(data, sshc, SSH_SFTP_CLOSE);
1905 sshc->nextstate = SSH_NO_STATE;
1906 }
1907 return result;
1908}
1909
1910static CURLcode ssh_state_sftp_next_quote(struct Curl_easy *data,
1911 struct ssh_conn *sshc)
1912{
1913 curlx_safefree(sshc->quote_path1);
1914 curlx_safefree(sshc->quote_path2);
1915
1916 sshc->quote_item = sshc->quote_item->next;
1917
1918 if(sshc->quote_item) {
1919 myssh_to(data, sshc, SSH_SFTP_QUOTE);
1920 }
1921 else {
1922 if(sshc->nextstate != SSH_NO_STATE) {
1923 myssh_to(data, sshc, sshc->nextstate);
1924 sshc->nextstate = SSH_NO_STATE;
1925 }
1926 else {
1927 myssh_to(data, sshc, SSH_SFTP_GETINFO);
1928 }
1929 }
1930 return CURLE_OK;
1931}
1932
1933static CURLcode ssh_state_sftp_quote_stat(struct Curl_easy *data,
1934 struct ssh_conn *sshc,
1935 struct SSHPROTO *sshp,
1936 bool *blockp)
1937{
1938 CURLcode result;
1939
1940 if(!sshp)
1941 return CURLE_FAILED_INIT;
1942
1943 result = sftp_quote_stat(data, sshc, sshp, blockp);
1944 if(result) {
1945 myssh_to(data, sshc, SSH_SFTP_CLOSE);
1946 sshc->nextstate = SSH_NO_STATE;
1947 }
1948 return result;
1949}
1950
1951static CURLcode ssh_state_sftp_quote_setstat(struct Curl_easy *data,
1952 struct ssh_conn *sshc,
1953 struct SSHPROTO *sshp)
1954{
1955 int rc;
1956
1957 if(!sshp)
1958 return CURLE_FAILED_INIT;
1959
1960 rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshc->quote_path2,
1961 curlx_uztoui(strlen(sshc->quote_path2)),
1962 LIBSSH2_SFTP_SETSTAT,
1963 &sshp->quote_attrs);
1964 if(rc == LIBSSH2_ERROR_EAGAIN)
1965 return CURLE_AGAIN;
1966
1967 if(rc && !sshc->acceptfail) {
1968 unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
1969 failf(data, "Attempt to set SFTP stats for \"%s\" failed: %s",
1970 sshc->quote_path2, sftp_libssh2_strerror(sftperr));
1971 curlx_safefree(sshc->quote_path1);
1972 curlx_safefree(sshc->quote_path2);
1973 myssh_to(data, sshc, SSH_SFTP_CLOSE);
1974 sshc->nextstate = SSH_NO_STATE;
1975 return CURLE_QUOTE_ERROR;
1976 }
1977 myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
1978 return CURLE_OK;
1979}
1980
1981static CURLcode ssh_state_sftp_quote_symlink(struct Curl_easy *data,
1982 struct ssh_conn *sshc)
1983{
1984 int rc =
1985 libssh2_sftp_symlink_ex(sshc->sftp_session, sshc->quote_path1,
1986 curlx_uztoui(strlen(sshc->quote_path1)),
1987 sshc->quote_path2,
1988 curlx_uztoui(strlen(sshc->quote_path2)),
1989 LIBSSH2_SFTP_SYMLINK);
1990 if(rc == LIBSSH2_ERROR_EAGAIN)
1991 return CURLE_AGAIN;
1992
1993 if(rc && !sshc->acceptfail) {
1994 unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
1995 failf(data, "symlink \"%s\" to \"%s\" failed: %s",
1996 sshc->quote_path1, sshc->quote_path2,
1997 sftp_libssh2_strerror(sftperr));
1998 curlx_safefree(sshc->quote_path1);
1999 curlx_safefree(sshc->quote_path2);
2000 myssh_to(data, sshc, SSH_SFTP_CLOSE);
2001 sshc->nextstate = SSH_NO_STATE;
2002 return CURLE_QUOTE_ERROR;
2003 }
2004 myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
2005 return CURLE_OK;
2006}
2007
2008static CURLcode ssh_state_sftp_quote_mkdir(struct Curl_easy *data,
2009 struct ssh_conn *sshc)
2010{
2011 int rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sshc->quote_path1,
2012 curlx_uztoui(strlen(sshc->quote_path1)),
2013 (long)data->set.new_directory_perms);
2014 if(rc == LIBSSH2_ERROR_EAGAIN)
2015 return CURLE_AGAIN;
2016
2017 if(rc && !sshc->acceptfail) {
2018 unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
2019 failf(data, "mkdir \"%s\" failed: %s",
2020 sshc->quote_path1, sftp_libssh2_strerror(sftperr));
2021 curlx_safefree(sshc->quote_path1);
2022 myssh_to(data, sshc, SSH_SFTP_CLOSE);
2023 sshc->nextstate = SSH_NO_STATE;
2024 return CURLE_QUOTE_ERROR;
2025 }
2026 myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
2027 return CURLE_OK;
2028}
2029
2030static CURLcode ssh_state_sftp_quote_rename(struct Curl_easy *data,
2031 struct ssh_conn *sshc)
2032{
2033 int rc =
2034 libssh2_sftp_rename_ex(sshc->sftp_session, sshc->quote_path1,
2035 curlx_uztoui(strlen(sshc->quote_path1)),
2036 sshc->quote_path2,
2037 curlx_uztoui(strlen(sshc->quote_path2)),
2038 LIBSSH2_SFTP_RENAME_OVERWRITE |
2039 LIBSSH2_SFTP_RENAME_ATOMIC |
2040 LIBSSH2_SFTP_RENAME_NATIVE);
2041
2042 if(rc == LIBSSH2_ERROR_EAGAIN)
2043 return CURLE_AGAIN;
2044
2045 if(rc && !sshc->acceptfail) {
2046 unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
2047 failf(data, "rename \"%s\" to \"%s\" failed: %s",
2048 sshc->quote_path1, sshc->quote_path2,
2049 sftp_libssh2_strerror(sftperr));
2050 curlx_safefree(sshc->quote_path1);
2051 curlx_safefree(sshc->quote_path2);
2052 myssh_to(data, sshc, SSH_SFTP_CLOSE);
2053 sshc->nextstate = SSH_NO_STATE;
2054 return CURLE_QUOTE_ERROR;
2055 }
2056 myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
2057 return CURLE_OK;
2058}
2059
2060static CURLcode ssh_state_sftp_quote_rmdir(struct Curl_easy *data,
2061 struct ssh_conn *sshc)
2062{
2063 int rc = libssh2_sftp_rmdir_ex(sshc->sftp_session, sshc->quote_path1,
2064 curlx_uztoui(strlen(sshc->quote_path1)));
2065 if(rc == LIBSSH2_ERROR_EAGAIN)
2066 return CURLE_AGAIN;
2067
2068 if(rc && !sshc->acceptfail) {
2069 unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
2070 failf(data, "rmdir \"%s\" failed: %s",
2071 sshc->quote_path1, sftp_libssh2_strerror(sftperr));
2072 curlx_safefree(sshc->quote_path1);
2073 myssh_to(data, sshc, SSH_SFTP_CLOSE);
2074 sshc->nextstate = SSH_NO_STATE;
2075 return CURLE_QUOTE_ERROR;
2076 }
2077 myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
2078 return CURLE_OK;
2079}
2080
2081static CURLcode ssh_state_sftp_quote_unlink(struct Curl_easy *data,
2082 struct ssh_conn *sshc)
2083{
2084 int rc = libssh2_sftp_unlink_ex(sshc->sftp_session, sshc->quote_path1,
2085 curlx_uztoui(strlen(sshc->quote_path1)));
2086 if(rc == LIBSSH2_ERROR_EAGAIN)
2087 return CURLE_AGAIN;
2088
2089 if(rc && !sshc->acceptfail) {
2090 unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
2091 failf(data, "rm \"%s\" failed: %s",
2092 sshc->quote_path1, sftp_libssh2_strerror(sftperr));
2093 curlx_safefree(sshc->quote_path1);
2094 myssh_to(data, sshc, SSH_SFTP_CLOSE);
2095 sshc->nextstate = SSH_NO_STATE;
2096 return CURLE_QUOTE_ERROR;
2097 }
2098 myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
2099 return CURLE_OK;
2100}
2101
2102static CURLcode ssh_state_sftp_quote_statvfs(struct Curl_easy *data,
2103 struct ssh_conn *sshc)
2104{
2105 LIBSSH2_SFTP_STATVFS statvfs;
2106 int rc = libssh2_sftp_statvfs(sshc->sftp_session, sshc->quote_path1,
2107 curlx_uztoui(strlen(sshc->quote_path1)),
2108 &statvfs);
2109
2110 if(rc == LIBSSH2_ERROR_EAGAIN)
2111 return CURLE_AGAIN;
2112
2113 if(rc && !sshc->acceptfail) {
2114 unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
2115 failf(data, "statvfs \"%s\" failed: %s",
2116 sshc->quote_path1, sftp_libssh2_strerror(sftperr));
2117 curlx_safefree(sshc->quote_path1);
2118 myssh_to(data, sshc, SSH_SFTP_CLOSE);
2119 sshc->nextstate = SSH_NO_STATE;
2120 return CURLE_QUOTE_ERROR;
2121 }
2122 else if(rc == 0) {
2123#ifdef _MSC_VER
2124#define CURL_LIBSSH2_VFS_SIZE_MASK "I64u"
2125#else
2126#define CURL_LIBSSH2_VFS_SIZE_MASK "llu"
2127#endif
2128 CURLcode result;
2129 char *tmp = curl_maprintf("statvfs:\n"
2130 "f_bsize: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
2131 "f_frsize: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
2132 "f_blocks: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
2133 "f_bfree: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
2134 "f_bavail: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
2135 "f_files: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
2136 "f_ffree: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
2137 "f_favail: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
2138 "f_fsid: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
2139 "f_flag: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n"
2140 "f_namemax: %" CURL_LIBSSH2_VFS_SIZE_MASK "\n",
2141 statvfs.f_bsize, statvfs.f_frsize,
2142 statvfs.f_blocks, statvfs.f_bfree,
2143 statvfs.f_bavail, statvfs.f_files,
2144 statvfs.f_ffree, statvfs.f_favail,
2145 statvfs.f_fsid, statvfs.f_flag,
2146 statvfs.f_namemax);
2147 if(!tmp) {
2148 myssh_to(data, sshc, SSH_SFTP_CLOSE);
2149 sshc->nextstate = SSH_NO_STATE;
2150 return CURLE_OUT_OF_MEMORY;
2151 }
2152
2153 result = Curl_client_write(data, CLIENTWRITE_HEADER, tmp, strlen(tmp));
2154 curlx_free(tmp);
2155 if(result) {
2156 myssh_to(data, sshc, SSH_SFTP_CLOSE);
2157 sshc->nextstate = SSH_NO_STATE;
2158 return result;
2159 }
2160 }
2161 myssh_to(data, sshc, SSH_SFTP_NEXT_QUOTE);
2162 return CURLE_OK;
2163}
2164
2165static CURLcode ssh_state_sftp_create_dirs_mkdir(struct Curl_easy *data,
2166 struct ssh_conn *sshc,
2167 struct SSHPROTO *sshp)
2168{
2169 /* 'mode' - parameter is preliminary - default to 0644 */
2170 int rc;
2171
2172 if(!sshp)
2173 return CURLE_FAILED_INIT;
2174
2175 rc = libssh2_sftp_mkdir_ex(sshc->sftp_session, sshp->path,
2176 curlx_uztoui(strlen(sshp->path)),
2177 (long)data->set.new_directory_perms);
2178 if(rc == LIBSSH2_ERROR_EAGAIN)
2179 return CURLE_AGAIN;
2180
2181 *sshc->slash_pos = '/';
2182 ++sshc->slash_pos;
2183 if(rc < 0) {
2184 /*
2185 * Abort if failure was not that the directory already exists or
2186 * the permission was denied (creation might succeed further down
2187 * the path) - retry on unspecific FAILURE also
2188 */
2189 unsigned long sftperr = libssh2_sftp_last_error(sshc->sftp_session);
2190 if((sftperr != LIBSSH2_FX_FILE_ALREADY_EXISTS) &&
2191 (sftperr != LIBSSH2_FX_FAILURE) &&
2192 (sftperr != LIBSSH2_FX_PERMISSION_DENIED)) {
2193 myssh_to(data, sshc, SSH_SFTP_CLOSE);
2194 return sftp_libssh2_error_to_CURLE(sftperr);
2195 }
2196 }
2197 myssh_to(data, sshc, SSH_SFTP_CREATE_DIRS);
2198 return CURLE_OK;
2199}
2200
2201static CURLcode ssh_state_sftp_readdir_init(struct Curl_easy *data,
2202 struct ssh_conn *sshc,
2203 struct SSHPROTO *sshp)
2204{
2205 if(!sshp)
2206 return CURLE_FAILED_INIT;
2207
2208 Curl_pgrsSetDownloadSize(data, -1);
2209 if(data->req.no_body) {
2210 myssh_to(data, sshc, SSH_STOP);
2211 return CURLE_OK;
2212 }
2213
2214 /*
2215 * This is a directory that we are trying to get, so produce a directory
2216 * listing
2217 */
2218 sshc->sftp_handle =
2219 libssh2_sftp_open_ex(sshc->sftp_session, sshp->path,
2220 curlx_uztoui(strlen(sshp->path)),
2221 0, 0, LIBSSH2_SFTP_OPENDIR);
2222 if(!sshc->sftp_handle) {
2223 unsigned long sftperr;
2224 if(libssh2_session_last_errno(sshc->ssh_session) == LIBSSH2_ERROR_EAGAIN)
2225 return CURLE_AGAIN;
2226
2227 sftperr = libssh2_sftp_last_error(sshc->sftp_session);
2228 failf(data, "Could not open directory for reading: %s",
2229 sftp_libssh2_strerror(sftperr));
2230 myssh_to(data, sshc, SSH_SFTP_CLOSE);
2231 return sftp_libssh2_error_to_CURLE(sftperr);
2232 }
2233 myssh_to(data, sshc, SSH_SFTP_READDIR);
2234 return CURLE_OK;
2235}
2236
2237static CURLcode ssh_state_sftp_readdir_link(struct Curl_easy *data,
2238 struct ssh_conn *sshc,
2239 struct SSHPROTO *sshp)
2240{
2241 CURLcode result;
2242 int rc;
2243 if(!sshp)
2244 return CURLE_FAILED_INIT;
2245
2246 rc = libssh2_sftp_symlink_ex(sshc->sftp_session,
2247 curlx_dyn_ptr(&sshp->readdir_link),
2248 (unsigned int)
2249 curlx_dyn_len(&sshp->readdir_link),
2250 sshp->readdir_filename,
2251 CURL_PATH_MAX, LIBSSH2_SFTP_READLINK);
2252 if(rc == LIBSSH2_ERROR_EAGAIN)
2253 return CURLE_AGAIN;
2254
2255 curlx_dyn_free(&sshp->readdir_link);
2256
2257 if(rc < 0)
2258 return CURLE_OUT_OF_MEMORY;
2259
2260 /* append filename and extra output */
2261 result = curlx_dyn_addf(&sshp->readdir, " -> %s", sshp->readdir_filename);
2262 if(result)
2263 myssh_to(data, sshc, SSH_SFTP_CLOSE);
2264 else
2265 myssh_to(data, sshc, SSH_SFTP_READDIR_BOTTOM);
2266 return result;
2267}
2268
2269static CURLcode ssh_state_scp_download_init(struct Curl_easy *data,
2270 struct ssh_conn *sshc,
2271 struct SSHPROTO *sshp)
2272{
2273 curl_off_t bytecount;
2274 libssh2_struct_stat sb;
2275
2276 if(!sshp)
2277 return CURLE_FAILED_INIT;
2278 /*
2279 * We must check the remote file; if it is a directory no values are
2280 * be set in sb
2281 */
2282
2283 /*
2284 * If support for >2GB files exists, use it.
2285 */
2286
2287 /* get a fresh new channel from the ssh layer */
2288 memset(&sb, 0, sizeof(libssh2_struct_stat));
2289 sshc->ssh_channel = libssh2_scp_recv2(sshc->ssh_session, sshp->path, &sb);
2290 if(!sshc->ssh_channel) {
2291 int ssh_err;
2292 char *err_msg = NULL;
2293
2294 if(libssh2_session_last_errno(sshc->ssh_session) ==
2295 LIBSSH2_ERROR_EAGAIN)
2296 return CURLE_AGAIN;
2297
2298 ssh_err = libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0);
2299 failf(data, "%s", err_msg);
2300 myssh_to(data, sshc, SSH_SCP_CHANNEL_FREE);
2301 return libssh2_session_error_to_CURLE(ssh_err);
2302 }
2303
2304 /* download data */
2305 bytecount = (curl_off_t)sb.st_size;
2306 data->req.maxdownload = (curl_off_t)sb.st_size;
2307 Curl_xfer_setup_recv(data, FIRSTSOCKET, bytecount);
2308
2309 /* not set by Curl_xfer_setup to preserve io_flags */
2310 data->conn->send_idx = 0;
2311
2312 myssh_to(data, sshc, SSH_STOP);
2313 return CURLE_OK;
2314}
2315
2316static CURLcode ssh_state_sftp_close(struct Curl_easy *data,
2317 struct ssh_conn *sshc,
2318 struct SSHPROTO *sshp)
2319{
2320 int rc = 0;
2321 if(!sshp)
2322 return CURLE_FAILED_INIT;
2323 if(sshc->sftp_handle) {
2324 rc = libssh2_sftp_close(sshc->sftp_handle);
2325 if(rc == LIBSSH2_ERROR_EAGAIN)
2326 return CURLE_AGAIN;
2327
2328 if(rc < 0) {
2329 char *err_msg = NULL;
2330 (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0);
2331 infof(data, "Failed to close libssh2 file: %d %s", rc, err_msg);
2332 }
2333 sshc->sftp_handle = NULL;
2334 }
2335
2336 curlx_safefree(sshp->path);
2337
2338 CURL_TRC_SSH(data, "SFTP DONE done");
2339
2340 /* Check if nextstate is set and move .nextstate could be POSTQUOTE_INIT
2341 After nextstate is executed, the control should come back to
2342 SSH_SFTP_CLOSE to pass the correct result back */
2343 if(sshc->nextstate != SSH_NO_STATE &&
2344 sshc->nextstate != SSH_SFTP_CLOSE) {
2345 myssh_to(data, sshc, sshc->nextstate);
2346 sshc->nextstate = SSH_SFTP_CLOSE;
2347 }
2348 else
2349 myssh_to(data, sshc, SSH_STOP);
2350
2351 return CURLE_OK;
2352}
2353
2354static CURLcode ssh_state_sftp_shutdown(struct Curl_easy *data,
2355 struct ssh_conn *sshc)
2356{
2357 /* during times we get here due to a broken transfer and then the
2358 sftp_handle might not have been taken down so make sure that is done
2359 before we proceed */
2360 int rc = 0;
2361 if(sshc->sftp_handle) {
2362 rc = libssh2_sftp_close(sshc->sftp_handle);
2363 if(rc == LIBSSH2_ERROR_EAGAIN)
2364 return CURLE_AGAIN;
2365
2366 if(rc < 0) {
2367 char *err_msg = NULL;
2368 (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0);
2369 infof(data, "Failed to close libssh2 file: %d %s", rc, err_msg);
2370 }
2371 sshc->sftp_handle = NULL;
2372 }
2373 if(sshc->sftp_session) {
2374 rc = libssh2_sftp_shutdown(sshc->sftp_session);
2375 if(rc == LIBSSH2_ERROR_EAGAIN)
2376 return CURLE_AGAIN;
2377
2378 if(rc < 0) {
2379 infof(data, "Failed to stop libssh2 sftp subsystem");
2380 }
2381 sshc->sftp_session = NULL;
2382 }
2383
2384 curlx_safefree(sshc->homedir);
2385
2386 myssh_to(data, sshc, SSH_SESSION_DISCONNECT);
2387 return CURLE_OK;
2388}
2389
2390static CURLcode ssh_state_sftp_download_init(struct Curl_easy *data,
2391 struct ssh_conn *sshc,
2392 struct SSHPROTO *sshp)
2393{
2394 if(!sshp)
2395 return CURLE_FAILED_INIT;
2396 /*
2397 * Work on getting the specified file
2398 */
2399 sshc->sftp_handle =
2400 libssh2_sftp_open_ex(sshc->sftp_session, sshp->path,
2401 curlx_uztoui(strlen(sshp->path)),
2402 LIBSSH2_FXF_READ, (long)data->set.new_file_perms,
2403 LIBSSH2_SFTP_OPENFILE);
2404 if(!sshc->sftp_handle) {
2405 unsigned long sftperr;
2406 if(libssh2_session_last_errno(sshc->ssh_session) ==
2407 LIBSSH2_ERROR_EAGAIN) {
2408 return CURLE_AGAIN;
2409 }
2410 sftperr = libssh2_sftp_last_error(sshc->sftp_session);
2411 failf(data, "Could not open remote file for reading: %s",
2412 sftp_libssh2_strerror(sftperr));
2413 myssh_to(data, sshc, SSH_SFTP_CLOSE);
2414 return sftp_libssh2_error_to_CURLE(sftperr);
2415 }
2416 myssh_to(data, sshc, SSH_SFTP_DOWNLOAD_STAT);
2417 return CURLE_OK;
2418}
2419
2420static CURLcode ssh_state_scp_upload_init(struct Curl_easy *data,
2421 struct ssh_conn *sshc,
2422 struct SSHPROTO *sshp)
2423{
2424 if(!sshp)
2425 return CURLE_FAILED_INIT;
2426 /*
2427 * libssh2 requires that the destination path is a full path that
2428 * includes the destination file and name OR ends in a "/" . If this is
2429 * not done the destination file is named the same name as the last
2430 * directory in the path.
2431 */
2432 sshc->ssh_channel =
2433 libssh2_scp_send64(sshc->ssh_session, sshp->path,
2434 (int)data->set.new_file_perms,
2435 (libssh2_int64_t)data->state.infilesize, 0, 0);
2436 if(!sshc->ssh_channel) {
2437 int ssh_err;
2438 char *err_msg = NULL;
2439 CURLcode result;
2440 if(libssh2_session_last_errno(sshc->ssh_session) ==
2441 LIBSSH2_ERROR_EAGAIN)
2442 return CURLE_AGAIN;
2443
2444 ssh_err = libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0);
2445 failf(data, "%s", err_msg);
2446 myssh_to(data, sshc, SSH_SCP_CHANNEL_FREE);
2447 result = libssh2_session_error_to_CURLE(ssh_err);
2448
2449 /* Map generic errors to upload failed */
2450 if(result == CURLE_SSH ||
2451 result == CURLE_REMOTE_FILE_NOT_FOUND)
2452 result = CURLE_UPLOAD_FAILED;
2453 return result;
2454 }
2455
2456 /* upload data */
2457 data->req.size = data->state.infilesize;
2458 Curl_pgrsSetUploadSize(data, data->state.infilesize);
2459 Curl_xfer_setup_send(data, FIRSTSOCKET);
2460
2461 /* not set by Curl_xfer_setup to preserve io_flags */
2462 data->conn->recv_idx = FIRSTSOCKET;
2463
2464 myssh_to(data, sshc, SSH_STOP);
2465
2466 return CURLE_OK;
2467}
2468
2469static CURLcode ssh_state_session_disconnect(struct Curl_easy *data,
2470 struct ssh_conn *sshc)
2471{
2472 /* during weird times when we have been prematurely aborted, the channel
2473 is still alive when we reach this state and we MUST kill the channel
2474 properly first */
2475 int rc = 0;
2476 if(sshc->ssh_channel) {
2477 rc = libssh2_channel_free(sshc->ssh_channel);
2478 if(rc == LIBSSH2_ERROR_EAGAIN)
2479 return CURLE_AGAIN;
2480
2481 if(rc < 0) {
2482 char *err_msg = NULL;
2483 (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0);
2484 infof(data, "Failed to free libssh2 scp subsystem: %d %s", rc, err_msg);
2485 }
2486 sshc->ssh_channel = NULL;
2487 }
2488
2489 if(sshc->ssh_session) {
2490 rc = libssh2_session_disconnect(sshc->ssh_session, "Shutdown");
2491 if(rc == LIBSSH2_ERROR_EAGAIN)
2492 return CURLE_AGAIN;
2493
2494 if(rc < 0) {
2495 char *err_msg = NULL;
2496 (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0);
2497 infof(data, "Failed to disconnect libssh2 session: %d %s", rc, err_msg);
2498 }
2499 }
2500
2501 curlx_safefree(sshc->homedir);
2502
2503 myssh_to(data, sshc, SSH_SESSION_FREE);
2504 return CURLE_OK;
2505}
2506
2507static CURLcode sshc_cleanup(struct ssh_conn *sshc, struct Curl_easy *data,
2508 bool block)
2509{
2510 int rc;
2511
2512 if(sshc->kh) {
2513 libssh2_knownhost_free(sshc->kh);
2514 sshc->kh = NULL;
2515 }
2516
2517 if(sshc->ssh_agent) {
2518 rc = libssh2_agent_disconnect(sshc->ssh_agent);
2519 if((rc < 0) && data) {
2520 char *err_msg = NULL;
2521 (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0);
2522 infof(data, "Failed to disconnect from libssh2 agent: %d %s",
2523 rc, err_msg);
2524 }
2525 if(!block && (rc == LIBSSH2_ERROR_EAGAIN))
2526 return CURLE_AGAIN;
2527
2528 libssh2_agent_free(sshc->ssh_agent);
2529 sshc->ssh_agent = NULL;
2530
2531 /* NB: there is no need to free identities, they are part of internal
2532 agent stuff */
2533 sshc->sshagent_identity = NULL;
2534 sshc->sshagent_prev_identity = NULL;
2535 }
2536
2537 if(sshc->sftp_handle) {
2538 rc = libssh2_sftp_close(sshc->sftp_handle);
2539 if((rc < 0) && data) {
2540 char *err_msg = NULL;
2541 (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0);
2542 infof(data, "Failed to close libssh2 file: %d %s", rc, err_msg);
2543 }
2544 if(!block && (rc == LIBSSH2_ERROR_EAGAIN))
2545 return CURLE_AGAIN;
2546
2547 sshc->sftp_handle = NULL;
2548 }
2549
2550 if(sshc->ssh_channel) {
2551 rc = libssh2_channel_free(sshc->ssh_channel);
2552 if((rc < 0) && data) {
2553 char *err_msg = NULL;
2554 (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0);
2555 infof(data, "Failed to free libssh2 scp subsystem: %d %s", rc, err_msg);
2556 }
2557 if(!block && (rc == LIBSSH2_ERROR_EAGAIN))
2558 return CURLE_AGAIN;
2559
2560 sshc->ssh_channel = NULL;
2561 }
2562
2563 if(sshc->sftp_session) {
2564 rc = libssh2_sftp_shutdown(sshc->sftp_session);
2565 if((rc < 0) && data) {
2566 char *err_msg = NULL;
2567 (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0);
2568 infof(data, "Failed to stop libssh2 sftp subsystem: %d %s", rc, err_msg);
2569 }
2570 if(!block && (rc == LIBSSH2_ERROR_EAGAIN))
2571 return CURLE_AGAIN;
2572
2573 sshc->sftp_session = NULL;
2574 }
2575
2576 if(sshc->ssh_session) {
2577 rc = libssh2_session_free(sshc->ssh_session);
2578 if((rc < 0) && data) {
2579 char *err_msg = NULL;
2580 (void)libssh2_session_last_error(sshc->ssh_session, &err_msg, NULL, 0);
2581 infof(data, "Failed to free libssh2 session: %d %s", rc, err_msg);
2582 }
2583 if(!block && (rc == LIBSSH2_ERROR_EAGAIN))
2584 return CURLE_AGAIN;
2585
2586 sshc->ssh_session = NULL;
2587 }
2588
2589 /* worst-case scenario cleanup */
2590 DEBUGASSERT(sshc->ssh_session == NULL);
2591 DEBUGASSERT(sshc->ssh_channel == NULL);
2592 DEBUGASSERT(sshc->sftp_session == NULL);
2593 DEBUGASSERT(sshc->sftp_handle == NULL);
2594 DEBUGASSERT(sshc->kh == NULL);
2595 DEBUGASSERT(sshc->ssh_agent == NULL);
2596
2597 curlx_safefree(sshc->rsa_pub);
2598 curlx_safefree(sshc->rsa);
2599 curlx_safefree(sshc->quote_path1);
2600 curlx_safefree(sshc->quote_path2);
2601 curlx_safefree(sshc->homedir);
2602
2603 return CURLE_OK;
2604}
2605
2606static CURLcode ssh_state_sftp_getinfo(struct Curl_easy *data,
2607 struct ssh_conn *sshc)
2608{
2609 if(data->set.get_filetime)
2610 myssh_to(data, sshc, SSH_SFTP_FILETIME);
2611 else
2612 myssh_to(data, sshc, SSH_SFTP_TRANS_INIT);
2613 return CURLE_OK;
2614}
2615
2616static CURLcode ssh_state_sftp_filetime(struct Curl_easy *data,
2617 struct ssh_conn *sshc,
2618 struct SSHPROTO *sshp)
2619{
2620 LIBSSH2_SFTP_ATTRIBUTES attrs;
2621 int rc;
2622
2623 if(!sshp)
2624 return CURLE_FAILED_INIT;
2625
2626 rc = libssh2_sftp_stat_ex(sshc->sftp_session, sshp->path,
2627 curlx_uztoui(strlen(sshp->path)),
2628 LIBSSH2_SFTP_STAT, &attrs);
2629 if(rc == LIBSSH2_ERROR_EAGAIN)
2630 return CURLE_AGAIN;
2631
2632 if(rc == 0)
2633 data->info.filetime = (time_t)attrs.mtime;
2634
2635 myssh_to(data, sshc, SSH_SFTP_TRANS_INIT);
2636 return CURLE_OK;
2637}
2638
2639static CURLcode ssh_state_sftp_trans_init(struct Curl_easy *data,
2640 struct ssh_conn *sshc,
2641 struct SSHPROTO *sshp)
2642{
2643 if(data->state.upload)
2644 myssh_to(data, sshc, SSH_SFTP_UPLOAD_INIT);
2645 else if(sshp) {
2646 size_t plen = strlen(sshp->path);
2647 if(plen && (sshp->path[plen - 1] == '/'))
2648 myssh_to(data, sshc, SSH_SFTP_READDIR_INIT);
2649 else
2650 myssh_to(data, sshc, SSH_SFTP_DOWNLOAD_INIT);
2651 }
2652 else
2653 return CURLE_FAILED_INIT;
2654 return CURLE_OK;
2655}
2656
2657static CURLcode ssh_state_sftp_upload_init(struct Curl_easy *data,
2658 struct ssh_conn *sshc,
2659 struct SSHPROTO *sshp,
2660 bool *block)
2661{
2662 CURLcode result;
2663 if(!sshp)
2664 return CURLE_FAILED_INIT;
2665 result = sftp_upload_init(data, sshc, sshp, block);
2666 if(result) {
2667 myssh_to(data, sshc, SSH_SFTP_CLOSE);
2668 sshc->nextstate = SSH_NO_STATE;
2669 }
2670 return result;
2671}
2672
2673static CURLcode ssh_state_sftp_create_dirs_init(struct Curl_easy *data,
2674 struct ssh_conn *sshc,
2675 struct SSHPROTO *sshp)
2676{
2677 if(!sshp)
2678 return CURLE_FAILED_INIT;
2679 if(strlen(sshp->path) > 1) {
2680 sshc->slash_pos = sshp->path + 1; /* ignore the leading '/' */
2681 myssh_to(data, sshc, SSH_SFTP_CREATE_DIRS);
2682 }
2683 else
2684 myssh_to(data, sshc, SSH_SFTP_UPLOAD_INIT);
2685 return CURLE_OK;
2686}
2687
2688static CURLcode ssh_state_sftp_create_dirs(struct Curl_easy *data,
2689 struct ssh_conn *sshc,
2690 struct SSHPROTO *sshp)
2691{
2692 if(!sshp)
2693 return CURLE_FAILED_INIT;
2694 sshc->slash_pos = strchr(sshc->slash_pos, '/');
2695 if(sshc->slash_pos) {
2696 *sshc->slash_pos = 0;
2697 infof(data, "Creating directory '%s'", sshp->path);
2698 myssh_to(data, sshc, SSH_SFTP_CREATE_DIRS_MKDIR);
2699 return CURLE_OK;
2700 }
2701 myssh_to(data, sshc, SSH_SFTP_UPLOAD_INIT);
2702 return CURLE_OK;
2703}
2704
2705static CURLcode ssh_state_sftp_readdir(struct Curl_easy *data,
2706 struct ssh_conn *sshc,
2707 struct SSHPROTO *sshp,
2708 bool *block)
2709{
2710 CURLcode result;
2711 if(!sshp)
2712 return CURLE_FAILED_INIT;
2713 result = sftp_readdir(data, sshc, sshp, block);
2714 if(result)
2715 myssh_to(data, sshc, SSH_SFTP_CLOSE);
2716 return result;
2717}
2718
2719static CURLcode ssh_state_sftp_readdir_bottom(struct Curl_easy *data,
2720 struct ssh_conn *sshc,
2721 struct SSHPROTO *sshp)
2722{
2723 CURLcode result;
2724 if(!sshp)
2725 return CURLE_FAILED_INIT;
2726
2727 result = curlx_dyn_addn(&sshp->readdir, "\n", 1);
2728 if(!result)
2729 result = Curl_client_write(data, CLIENTWRITE_BODY,
2730 curlx_dyn_ptr(&sshp->readdir),
2731 curlx_dyn_len(&sshp->readdir));
2732 if(result) {
2733 curlx_dyn_free(&sshp->readdir);
2734 myssh_to(data, sshc, SSH_STOP);
2735 }
2736 else {
2737 curlx_dyn_reset(&sshp->readdir);
2738 myssh_to(data, sshc, SSH_SFTP_READDIR);
2739 }
2740 return result;
2741}
2742
2743static CURLcode ssh_state_sftp_readdir_done(struct Curl_easy *data,
2744 struct ssh_conn *sshc)
2745{
2746 if(libssh2_sftp_closedir(sshc->sftp_handle) ==
2747 LIBSSH2_ERROR_EAGAIN)
2748 return CURLE_AGAIN;
2749
2750 sshc->sftp_handle = NULL;
2751
2752 /* no data to transfer */
2753 Curl_xfer_setup_nop(data);
2754 myssh_to(data, sshc, SSH_STOP);
2755 return CURLE_OK;
2756}
2757
2758static CURLcode ssh_state_sftp_download_stat(struct Curl_easy *data,
2759 struct ssh_conn *sshc,
2760 struct SSHPROTO *sshp,
2761 bool *block)
2762{
2763 CURLcode result;
2764 if(!sshp)
2765 return CURLE_FAILED_INIT;
2766 result = sftp_download_stat(data, sshc, sshp, block);
2767 if(result) {
2768 myssh_to(data, sshc, SSH_SFTP_CLOSE);
2769 sshc->nextstate = SSH_NO_STATE;
2770 }
2771 return result;
2772}
2773
2774static CURLcode ssh_state_scp_trans_init(struct Curl_easy *data,
2775 struct ssh_conn *sshc,
2776 struct SSHPROTO *sshp)
2777{
2778 CURLcode result;
2779 if(!sshp)
2780 return CURLE_FAILED_INIT;
2781 result = Curl_getworkingpath(data, sshc->homedir,
2782 &sshp->path);
2783 if(result) {
2784 myssh_to(data, sshc, SSH_STOP);
2785 return result;
2786 }
2787
2788 if(data->state.upload) {
2789 if(data->state.infilesize < 0) {
2790 failf(data, "SCP requires a known file size for upload");
2791 myssh_to(data, sshc, SSH_SCP_CHANNEL_FREE);
2792 return CURLE_UPLOAD_FAILED;
2793 }
2794 myssh_to(data, sshc, SSH_SCP_UPLOAD_INIT);
2795 }
2796 else
2797 myssh_to(data, sshc, SSH_SCP_DOWNLOAD_INIT);
2798 return CURLE_OK;
2799}
2800
2801static CURLcode ssh_state_scp_done(struct Curl_easy *data,
2802 struct ssh_conn *sshc)
2803{
2804 if(data->state.upload)
2805 myssh_to(data, sshc, SSH_SCP_SEND_EOF);
2806 else
2807 myssh_to(data, sshc, SSH_SCP_CHANNEL_FREE);
2808 return CURLE_OK;
2809}
2810
2811static CURLcode ssh_state_scp_send_eof(struct Curl_easy *data,
2812 struct ssh_conn *sshc)
2813{
2814 if(sshc->ssh_channel) {
2815 int rc = libssh2_channel_send_eof(sshc->ssh_channel);
2816 if(rc == LIBSSH2_ERROR_EAGAIN)
2817 return CURLE_AGAIN;
2818 if(rc) {
2819 char *err_msg = NULL;
2820 (void)libssh2_session_last_error(sshc->ssh_session,
2821 &err_msg, NULL, 0);
2822 infof(data,
2823 "Failed to send libssh2 channel EOF: %d %s",
2824 rc, err_msg);
2825 }
2826 }
2827 myssh_to(data, sshc, SSH_SCP_WAIT_EOF);
2828 return CURLE_OK;
2829}
2830
2831static CURLcode ssh_state_scp_wait_eof(struct Curl_easy *data,
2832 struct ssh_conn *sshc)
2833{
2834 if(sshc->ssh_channel) {
2835 int rc = libssh2_channel_wait_eof(sshc->ssh_channel);
2836 if(rc == LIBSSH2_ERROR_EAGAIN)
2837 return CURLE_AGAIN;
2838 if(rc) {
2839 char *err_msg = NULL;
2840 (void)libssh2_session_last_error(sshc->ssh_session,
2841 &err_msg, NULL, 0);
2842 infof(data, "Failed to get channel EOF: %d %s",
2843 rc, err_msg);
2844 }
2845 }
2846 myssh_to(data, sshc, SSH_SCP_WAIT_CLOSE);
2847 return CURLE_OK;
2848}
2849
2850static CURLcode ssh_state_scp_wait_close(struct Curl_easy *data,
2851 struct ssh_conn *sshc)
2852{
2853 if(sshc->ssh_channel) {
2854 int rc =
2855 libssh2_channel_wait_closed(sshc->ssh_channel);
2856 if(rc == LIBSSH2_ERROR_EAGAIN)
2857 return CURLE_AGAIN;
2858 if(rc) {
2859 char *err_msg = NULL;
2860 (void)libssh2_session_last_error(sshc->ssh_session,
2861 &err_msg, NULL, 0);
2862 infof(data, "Channel failed to close: %d %s",
2863 rc, err_msg);
2864 }
2865 }
2866 myssh_to(data, sshc, SSH_SCP_CHANNEL_FREE);
2867 return CURLE_OK;
2868}
2869
2870static CURLcode ssh_state_scp_channel_free(
2871 struct Curl_easy *data,
2872 struct ssh_conn *sshc)
2873{
2874 if(sshc->ssh_channel) {
2875 int rc = libssh2_channel_free(sshc->ssh_channel);
2876 if(rc == LIBSSH2_ERROR_EAGAIN)
2877 return CURLE_AGAIN;
2878 if(rc < 0) {
2879 char *err_msg = NULL;
2880 (void)libssh2_session_last_error(sshc->ssh_session,
2881 &err_msg, NULL, 0);
2882 infof(data,
2883 "Failed to free libssh2 scp subsystem: %d %s",
2884 rc, err_msg);
2885 }
2886 sshc->ssh_channel = NULL;
2887 }
2888 CURL_TRC_SSH(data, "SCP DONE phase complete");
2889 myssh_to(data, sshc, SSH_STOP);
2890 return CURLE_OK;
2891}
2892
2893static CURLcode ssh_state_session_free(struct Curl_easy *data,
2894 struct ssh_conn *sshc)
2895{
2896 CURLcode result = sshc_cleanup(sshc, data, FALSE);
2897 struct connectdata *conn = data->conn;
2898 if(result)
2899 return result;
2900 memset(sshc, 0, sizeof(struct ssh_conn));
2901 connclose(conn, "SSH session free");
2902 sshc->state = SSH_SESSION_FREE; /* current */
2903 myssh_to(data, sshc, SSH_STOP);
2904 return CURLE_OK;
2905}
2906
2907/*
2908 * ssh_statemachine() runs the SSH state machine as far as it can without
2909 * blocking and without reaching the end. The data the pointer 'block' points
2910 * to is set to TRUE if the libssh2 function returns LIBSSH2_ERROR_EAGAIN
2911 * meaning it wants to be called again when the socket is ready
2912 */
2913static CURLcode ssh_statemachine(struct Curl_easy *data,
2914 struct ssh_conn *sshc,
2915 struct SSHPROTO *sshp,
2916 bool *block)
2917{
2918 CURLcode result = CURLE_OK;
2919 *block = 0; /* we are not blocking by default */
2920
2921 do {
2922 switch(sshc->state) {
2923 case SSH_INIT:
2924 result = ssh_state_init(data, sshc);
2925 if(result)
2926 break;
2927 FALLTHROUGH();
2928
2929 case SSH_S_STARTUP:
2930 result = ssh_state_startup(data, sshc);
2931 if(result)
2932 break;
2933 FALLTHROUGH();
2934
2935 case SSH_HOSTKEY:
2936 result = ssh_state_hostkey(data, sshc);
2937 break;
2938
2939 case SSH_AUTHLIST:
2940 result = ssh_state_authlist(data, sshc);
2941 break;
2942
2943 case SSH_AUTH_PKEY_INIT:
2944 result = ssh_state_pkey_init(data, sshc);
2945 break;
2946
2947 case SSH_AUTH_PKEY:
2948 result = ssh_state_auth_pkey(data, sshc);
2949 break;
2950
2951 case SSH_AUTH_PASS_INIT:
2952 result = ssh_state_auth_pass_init(data, sshc);
2953 break;
2954
2955 case SSH_AUTH_PASS:
2956 result = ssh_state_auth_pass(data, sshc);
2957 break;
2958
2959 case SSH_AUTH_HOST_INIT:
2960 result = ssh_state_auth_host_init(data, sshc);
2961 break;
2962
2963 case SSH_AUTH_HOST:
2964 myssh_to(data, sshc, SSH_AUTH_AGENT_INIT);
2965 break;
2966
2967 case SSH_AUTH_AGENT_INIT:
2968 result = ssh_state_auth_agent_init(data, sshc);
2969 break;
2970
2971 case SSH_AUTH_AGENT_LIST:
2972 result = ssh_state_auth_agent_list(data, sshc);
2973 break;
2974
2975 case SSH_AUTH_AGENT:
2976 result = ssh_state_auth_agent(data, sshc);
2977 break;
2978
2979 case SSH_AUTH_KEY_INIT:
2980 result = ssh_state_auth_key_init(data, sshc);
2981 break;
2982
2983 case SSH_AUTH_KEY:
2984 result = ssh_state_auth_key(data, sshc);
2985 break;
2986
2987 case SSH_AUTH_DONE:
2988 result = ssh_state_auth_done(data, sshc);
2989 break;
2990
2991 case SSH_SFTP_INIT:
2992 result = ssh_state_sftp_init(data, sshc);
2993 break;
2994
2995 case SSH_SFTP_REALPATH:
2996 result = ssh_state_sftp_realpath(data, sshc, sshp);
2997 break;
2998
2999 case SSH_SFTP_QUOTE_INIT:
3000 result = ssh_state_sftp_quote_init(data, sshc, sshp);
3001 break;
3002
3003 case SSH_SFTP_POSTQUOTE_INIT:
3004 result = ssh_state_sftp_postquote_init(data, sshc);
3005 break;
3006
3007 case SSH_SFTP_QUOTE:
3008 result = ssh_state_sftp_quote(data, sshc, sshp);
3009 break;
3010
3011 case SSH_SFTP_NEXT_QUOTE:
3012 result = ssh_state_sftp_next_quote(data, sshc);
3013 break;
3014
3015 case SSH_SFTP_QUOTE_STAT:
3016 result = ssh_state_sftp_quote_stat(data, sshc, sshp, block);
3017 break;
3018
3019 case SSH_SFTP_QUOTE_SETSTAT:
3020 result = ssh_state_sftp_quote_setstat(data, sshc, sshp);
3021 break;
3022
3023 case SSH_SFTP_QUOTE_SYMLINK:
3024 result = ssh_state_sftp_quote_symlink(data, sshc);
3025 break;
3026
3027 case SSH_SFTP_QUOTE_MKDIR:
3028 result = ssh_state_sftp_quote_mkdir(data, sshc);
3029 break;
3030
3031 case SSH_SFTP_QUOTE_RENAME:
3032 result = ssh_state_sftp_quote_rename(data, sshc);
3033 break;
3034
3035 case SSH_SFTP_QUOTE_RMDIR:
3036 result = ssh_state_sftp_quote_rmdir(data, sshc);
3037 break;
3038
3039 case SSH_SFTP_QUOTE_UNLINK:
3040 result = ssh_state_sftp_quote_unlink(data, sshc);
3041 break;
3042
3043 case SSH_SFTP_QUOTE_STATVFS:
3044 result = ssh_state_sftp_quote_statvfs(data, sshc);
3045 break;
3046
3047 case SSH_SFTP_GETINFO:
3048 result = ssh_state_sftp_getinfo(data, sshc);
3049 break;
3050
3051 case SSH_SFTP_FILETIME:
3052 result = ssh_state_sftp_filetime(data, sshc, sshp);
3053 break;
3054
3055 case SSH_SFTP_TRANS_INIT:
3056 result = ssh_state_sftp_trans_init(data, sshc, sshp);
3057 break;
3058
3059 case SSH_SFTP_UPLOAD_INIT:
3060 result = ssh_state_sftp_upload_init(data, sshc, sshp, block);
3061 break;
3062
3063 case SSH_SFTP_CREATE_DIRS_INIT:
3064 result = ssh_state_sftp_create_dirs_init(data, sshc, sshp);
3065 break;
3066
3067 case SSH_SFTP_CREATE_DIRS:
3068 result = ssh_state_sftp_create_dirs(data, sshc, sshp);
3069 break;
3070
3071 case SSH_SFTP_CREATE_DIRS_MKDIR:
3072 result = ssh_state_sftp_create_dirs_mkdir(data, sshc, sshp);
3073 break;
3074
3075 case SSH_SFTP_READDIR_INIT:
3076 result = ssh_state_sftp_readdir_init(data, sshc, sshp);
3077 break;
3078
3079 case SSH_SFTP_READDIR:
3080 result = ssh_state_sftp_readdir(data, sshc, sshp, block);
3081 break;
3082
3083 case SSH_SFTP_READDIR_LINK:
3084 result = ssh_state_sftp_readdir_link(data, sshc, sshp);
3085 break;
3086
3087 case SSH_SFTP_READDIR_BOTTOM:
3088 result = ssh_state_sftp_readdir_bottom(data, sshc, sshp);
3089 break;
3090
3091 case SSH_SFTP_READDIR_DONE:
3092 result = ssh_state_sftp_readdir_done(data, sshc);
3093 break;
3094
3095 case SSH_SFTP_DOWNLOAD_INIT:
3096 result = ssh_state_sftp_download_init(data, sshc, sshp);
3097 break;
3098
3099 case SSH_SFTP_DOWNLOAD_STAT:
3100 result = ssh_state_sftp_download_stat(data, sshc, sshp, block);
3101 break;
3102
3103 case SSH_SFTP_CLOSE:
3104 result = ssh_state_sftp_close(data, sshc, sshp);
3105 break;
3106
3107 case SSH_SFTP_SHUTDOWN:
3108 result = ssh_state_sftp_shutdown(data, sshc);
3109 break;
3110
3111 case SSH_SCP_TRANS_INIT:
3112 result = ssh_state_scp_trans_init(data, sshc, sshp);
3113 break;
3114
3115 case SSH_SCP_UPLOAD_INIT:
3116 result = ssh_state_scp_upload_init(data, sshc, sshp);
3117 break;
3118
3119 case SSH_SCP_DOWNLOAD_INIT:
3120 result = ssh_state_scp_download_init(data, sshc, sshp);
3121 break;
3122
3123 case SSH_SCP_DONE:
3124 result = ssh_state_scp_done(data, sshc);
3125 break;
3126
3127 case SSH_SCP_SEND_EOF:
3128 result = ssh_state_scp_send_eof(data, sshc);
3129 break;
3130
3131 case SSH_SCP_WAIT_EOF:
3132 result = ssh_state_scp_wait_eof(data, sshc);
3133 break;
3134
3135 case SSH_SCP_WAIT_CLOSE:
3136 result = ssh_state_scp_wait_close(data, sshc);
3137 break;
3138
3139 case SSH_SCP_CHANNEL_FREE:
3140 result = ssh_state_scp_channel_free(data, sshc);
3141 break;
3142
3143 case SSH_SESSION_DISCONNECT:
3144 result = ssh_state_session_disconnect(data, sshc);
3145 break;
3146
3147 case SSH_SESSION_FREE:
3148 result = ssh_state_session_free(data, sshc);
3149 break;
3150
3151 case SSH_QUIT:
3152 default:
3153 /* internal error */
3154 myssh_to(data, sshc, SSH_STOP);
3155 break;
3156 }
3157
3158 } while(!result && (sshc->state != SSH_STOP) && !*block);
3159
3160 if(result == CURLE_AGAIN) {
3161 /* we would block, we need to wait for the socket to be ready (in the
3162 right direction too)! */
3163 *block = TRUE;
3164 result = CURLE_OK;
3165 }
3166 CURL_TRC_SSH(data, "[%s] statemachine() -> %d, block=%d",
3167 Curl_ssh_statename(sshc->state), result, *block);
3168
3169 return result;
3170}
3171
3172/* called by the multi interface to figure out what socket(s) to wait for and
3173 for what actions in the DO_DONE, PERFORM and WAITPERFORM states */
3174static CURLcode ssh_pollset(struct Curl_easy *data,
3175 struct easy_pollset *ps)
3176{
3177 struct connectdata *conn = data->conn;
3178 struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
3179 curl_socket_t sock = conn->sock[FIRSTSOCKET];
3180 int waitfor;
3181
3182 if(!sshc || (sock == CURL_SOCKET_BAD))
3183 return CURLE_FAILED_INIT;
3184
3185 waitfor = sshc->waitfor ? sshc->waitfor : data->req.io_flags;
3186 if(waitfor) {
3187 int flags = 0;
3188 if(waitfor & REQ_IO_RECV)
3189 flags |= CURL_POLL_IN;
3190 if(waitfor & REQ_IO_SEND)
3191 flags |= CURL_POLL_OUT;
3192 DEBUGASSERT(flags);
3193 CURL_TRC_SSH(data, "pollset, flags=%x", flags);
3194 return Curl_pollset_change(data, ps, sock, flags, 0);
3195 }
3196 /* While we still have a session, we listen incoming data. */
3197 if(sshc->ssh_session)
3198 return Curl_pollset_change(data, ps, sock, CURL_POLL_IN, 0);
3199 return CURLE_OK;
3200}
3201
3202/*
3203 * When one of the libssh2 functions has returned LIBSSH2_ERROR_EAGAIN this
3204 * function is used to figure out in what direction and stores this info so
3205 * that the multi interface can take advantage of it. Make sure to call this
3206 * function in all cases so that when it _does not_ return EAGAIN we can
3207 * restore the default wait bits.
3208 */
3209static void ssh_block2waitfor(struct Curl_easy *data,
3210 struct ssh_conn *sshc,
3211 bool block)
3212{
3213 int dir = 0;
3214 (void)data;
3215 if(block) {
3216 dir = libssh2_session_block_directions(sshc->ssh_session);
3217 if(dir) {
3218 /* translate the libssh2 define bits into our own bit defines */
3219 sshc->waitfor =
3220 ((dir & LIBSSH2_SESSION_BLOCK_INBOUND) ? REQ_IO_RECV : 0) |
3221 ((dir & LIBSSH2_SESSION_BLOCK_OUTBOUND) ? REQ_IO_SEND : 0);
3222 }
3223 }
3224 if(!dir)
3225 sshc->waitfor = 0;
3226}
3227
3228/* called repeatedly until done from multi.c */
3229static CURLcode ssh_multi_statemach(struct Curl_easy *data, bool *done)
3230{
3231 struct connectdata *conn = data->conn;
3232 struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
3233 struct SSHPROTO *sshp = Curl_meta_get(data, CURL_META_SSH_EASY);
3234 CURLcode result = CURLE_OK;
3235 bool block; /* we store the status and use that to provide a ssh_pollset()
3236 implementation */
3237 if(!sshc || !sshp)
3238 return CURLE_FAILED_INIT;
3239
3240 do {
3241 result = ssh_statemachine(data, sshc, sshp, &block);
3242 *done = (sshc->state == SSH_STOP);
3243 /* if there is no error, it is not done and it did not EWOULDBLOCK, then
3244 try again */
3245 } while(!result && !*done && !block);
3246 ssh_block2waitfor(data, sshc, block);
3247
3248 return result;
3249}
3250
3251static CURLcode ssh_block_statemach(struct Curl_easy *data,
3252 struct ssh_conn *sshc,
3253 struct SSHPROTO *sshp,
3254 bool disconnect)
3255{
3256 CURLcode result = CURLE_OK;
3257 struct curltime start = *Curl_pgrs_now(data);
3258
3259 while((sshc->state != SSH_STOP) && !result) {
3260 bool block;
3261 timediff_t left_ms = 1000;
3262
3263 result = ssh_statemachine(data, sshc, sshp, &block);
3264 if(result)
3265 break;
3266
3267 if(!disconnect) {
3268 result = Curl_pgrsCheck(data);
3269 if(result)
3270 break;
3271
3272 left_ms = Curl_timeleft_ms(data);
3273 if(left_ms < 0) {
3274 failf(data, "Operation timed out");
3275 return CURLE_OPERATION_TIMEDOUT;
3276 }
3277 }
3278 else if(curlx_ptimediff_ms(Curl_pgrs_now(data), &start) > 1000) {
3279 /* disconnect timeout */
3280 failf(data, "Disconnect timed out");
3281 result = CURLE_OK;
3282 break;
3283 }
3284
3285 if(block) {
3286 int dir = libssh2_session_block_directions(sshc->ssh_session);
3287 curl_socket_t sock = data->conn->sock[FIRSTSOCKET];
3288 curl_socket_t fd_read = CURL_SOCKET_BAD;
3289 curl_socket_t fd_write = CURL_SOCKET_BAD;
3290 if(LIBSSH2_SESSION_BLOCK_INBOUND & dir)
3291 fd_read = sock;
3292 if(LIBSSH2_SESSION_BLOCK_OUTBOUND & dir)
3293 fd_write = sock;
3294 /* wait for the socket to become ready */
3295 (void)Curl_socket_check(fd_read, CURL_SOCKET_BAD, fd_write,
3296 left_ms > 1000 ? 1000 : left_ms);
3297 }
3298 }
3299
3300 return result;
3301}
3302
3303static void myssh_easy_dtor(void *key, size_t klen, void *entry)
3304{
3305 struct SSHPROTO *sshp = entry;
3306 (void)key;
3307 (void)klen;
3308 curlx_safefree(sshp->path);
3309 curlx_dyn_free(&sshp->readdir);
3310 curlx_dyn_free(&sshp->readdir_link);
3311 curlx_free(sshp);
3312}
3313
3314static void myssh_conn_dtor(void *key, size_t klen, void *entry)
3315{
3316 struct ssh_conn *sshc = entry;
3317 (void)key;
3318 (void)klen;
3319 sshc_cleanup(sshc, NULL, TRUE);
3320 curlx_free(sshc);
3321}
3322
3323/*
3324 * SSH setup and connection
3325 */
3326static CURLcode ssh_setup_connection(struct Curl_easy *data,
3327 struct connectdata *conn)
3328{
3329 struct ssh_conn *sshc;
3330 struct SSHPROTO *sshp;
3331 (void)conn;
3332
3333 sshc = curlx_calloc(1, sizeof(*sshc));
3334 if(!sshc)
3335 return CURLE_OUT_OF_MEMORY;
3336
3337 if(Curl_conn_meta_set(conn, CURL_META_SSH_CONN, sshc, myssh_conn_dtor))
3338 return CURLE_OUT_OF_MEMORY;
3339
3340 sshp = curlx_calloc(1, sizeof(*sshp));
3341 if(!sshp)
3342 return CURLE_OUT_OF_MEMORY;
3343
3344 curlx_dyn_init(&sshp->readdir, CURL_PATH_MAX * 2);
3345 curlx_dyn_init(&sshp->readdir_link, CURL_PATH_MAX);
3346 if(Curl_meta_set(data, CURL_META_SSH_EASY, sshp, myssh_easy_dtor))
3347 return CURLE_OUT_OF_MEMORY;
3348
3349 return CURLE_OK;
3350}
3351
3352static Curl_recv scp_recv, sftp_recv;
3353static Curl_send scp_send, sftp_send;
3354
3355#ifndef CURL_DISABLE_PROXY
3356static ssize_t ssh_tls_recv(libssh2_socket_t sock, void *buffer,
3357 size_t length, int flags, void **abstract)
3358{
3359 struct Curl_easy *data = (struct Curl_easy *)*abstract;
3360 int sockindex = Curl_conn_sockindex(data, sock);
3361 size_t nread;
3362 CURLcode result;
3363 struct connectdata *conn = data->conn;
3364 Curl_recv *backup = conn->recv[sockindex];
3365 struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
3366 (void)flags;
3367
3368 if(!sshc)
3369 return -1;
3370
3371 /* swap in the TLS reader function for this call only, and then swap back
3372 the SSH one again */
3373 conn->recv[sockindex] = sshc->tls_recv;
3374 result = Curl_conn_recv(data, sockindex, buffer, length, &nread);
3375 conn->recv[sockindex] = backup;
3376 if(result == CURLE_AGAIN)
3377 return -EAGAIN; /* magic return code for libssh2 */
3378 else if(result)
3379 return -1; /* generic error */
3380 Curl_debug(data, CURLINFO_DATA_IN, (const char *)buffer, nread);
3381 return (ssize_t)nread;
3382}
3383
3384static ssize_t ssh_tls_send(libssh2_socket_t sock, const void *buffer,
3385 size_t length, int flags, void **abstract)
3386{
3387 struct Curl_easy *data = (struct Curl_easy *)*abstract;
3388 int sockindex = Curl_conn_sockindex(data, sock);
3389 size_t nwrite;
3390 CURLcode result;
3391 struct connectdata *conn = data->conn;
3392 Curl_send *backup = conn->send[sockindex];
3393 struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
3394 (void)flags;
3395
3396 if(!sshc)
3397 return -1;
3398
3399 /* swap in the TLS writer function for this call only, and then swap back
3400 the SSH one again */
3401 conn->send[sockindex] = sshc->tls_send;
3402 result = Curl_conn_send(data, sockindex, buffer, length, FALSE, &nwrite);
3403 conn->send[sockindex] = backup;
3404 if(result == CURLE_AGAIN)
3405 return -EAGAIN; /* magic return code for libssh2 */
3406 else if(result)
3407 return -1; /* error */
3408 Curl_debug(data, CURLINFO_DATA_OUT, (const char *)buffer, nwrite);
3409 return (ssize_t)nwrite;
3410}
3411#endif
3412
3413/*
3414 * Curl_ssh_connect() gets called from Curl_protocol_connect() to allow us to
3415 * do protocol-specific actions at connect-time.
3416 */
3417static CURLcode ssh_connect(struct Curl_easy *data, bool *done)
3418{
3419#ifdef CURL_LIBSSH2_DEBUG
3420 curl_socket_t sock;
3421#endif
3422 struct connectdata *conn = data->conn;
3423 struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
3424 CURLcode result;
3425
3426#if LIBSSH2_VERSION_NUM >= 0x010b00
3427 {
3428 const char *crypto_str;
3429 switch(libssh2_crypto_engine()) {
3430 case libssh2_gcrypt:
3431 crypto_str = "libgcrypt";
3432 break;
3433 case libssh2_mbedtls:
3434 crypto_str = "mbedTLS";
3435 break;
3436 case libssh2_openssl:
3437 crypto_str = "openssl compatible";
3438 break;
3439 case libssh2_os400qc3:
3440 crypto_str = "OS400QC3";
3441 break;
3442 case libssh2_wincng:
3443 crypto_str = "WinCNG";
3444 break;
3445 default:
3446 crypto_str = NULL;
3447 break;
3448 }
3449 if(crypto_str)
3450 infof(data, "libssh2 cryptography backend: %s", crypto_str);
3451 }
3452#endif
3453
3454 if(!sshc)
3455 return CURLE_FAILED_INIT;
3456
3457 infof(data, "User: '%s'", Curl_creds_user(conn->creds));
3458#ifdef CURL_LIBSSH2_DEBUG
3459 infof(data, "Password: %s", Curl_creds_passwd(conn->creds));
3460 sock = conn->sock[FIRSTSOCKET];
3461#endif /* CURL_LIBSSH2_DEBUG */
3462
3463 /* libcurl MUST to set custom memory functions so that the kbd_callback
3464 function's memory allocations can be properly freed */
3465 sshc->ssh_session = libssh2_session_init_ex(my_libssh2_malloc,
3466 my_libssh2_free,
3467 my_libssh2_realloc, data);
3468
3469 if(!sshc->ssh_session) {
3470 failf(data, "Failure initialising ssh session");
3471 return CURLE_FAILED_INIT;
3472 }
3473
3474 /* Set the packet read timeout if the libssh2 version supports it */
3475#if LIBSSH2_VERSION_NUM >= 0x010B00
3476 if(data->set.server_response_timeout > 0) {
3477 libssh2_session_set_read_timeout(sshc->ssh_session,
3478 (long)(data->set.server_response_timeout / 1000));
3479 }
3480#endif
3481
3482#ifndef CURL_DISABLE_PROXY
3483 if(conn->http_proxy.proxytype == CURLPROXY_HTTPS) {
3484 /*
3485 Setup libssh2 callbacks to make it read/write TLS from the socket.
3486
3487 ssize_t
3488 recvcb(libssh2_socket_t sock, void *buffer, size_t length,
3489 int flags, void **abstract);
3490
3491 ssize_t
3492 sendcb(libssh2_socket_t sock, const void *buffer, size_t length,
3493 int flags, void **abstract);
3494
3495 */
3496#if LIBSSH2_VERSION_NUM >= 0x010b01
3497 infof(data, "Uses HTTPS proxy");
3498#if defined(__clang__) && __clang_major__ >= 16
3499#pragma clang diagnostic push
3500#pragma clang diagnostic ignored "-Wcast-function-type-strict"
3501#endif
3502 libssh2_session_callback_set2(sshc->ssh_session,
3503 LIBSSH2_CALLBACK_RECV,
3504 (libssh2_cb_generic *)ssh_tls_recv);
3505 libssh2_session_callback_set2(sshc->ssh_session,
3506 LIBSSH2_CALLBACK_SEND,
3507 (libssh2_cb_generic *)ssh_tls_send);
3508#if defined(__clang__) && __clang_major__ >= 16
3509#pragma clang diagnostic pop
3510#endif
3511#else
3512 /*
3513 * This crazy union dance is here to avoid assigning a void pointer a
3514 * function pointer as it is invalid C. The problem is of course that
3515 * libssh2 has such an API...
3516 */
3517 union receive {
3518 void *recvp;
3519 ssize_t (*recvptr)(libssh2_socket_t, void *, size_t, int, void **);
3520 };
3521 union transfer {
3522 void *sendp;
3523 ssize_t (*sendptr)(libssh2_socket_t, const void *, size_t, int, void **);
3524 };
3525 union receive sshrecv;
3526 union transfer sshsend;
3527
3528 sshrecv.recvptr = ssh_tls_recv;
3529 sshsend.sendptr = ssh_tls_send;
3530
3531 infof(data, "Uses HTTPS proxy");
3532 libssh2_session_callback_set(sshc->ssh_session,
3533 LIBSSH2_CALLBACK_RECV, sshrecv.recvp);
3534 libssh2_session_callback_set(sshc->ssh_session,
3535 LIBSSH2_CALLBACK_SEND, sshsend.sendp);
3536#endif
3537
3538 /* Store the underlying TLS recv/send function pointers to be used when
3539 reading from the proxy */
3540 sshc->tls_recv = conn->recv[FIRSTSOCKET];
3541 sshc->tls_send = conn->send[FIRSTSOCKET];
3542 }
3543
3544#endif /* CURL_DISABLE_PROXY */
3545 if(conn->scheme->protocol & CURLPROTO_SCP) {
3546 conn->recv[FIRSTSOCKET] = scp_recv;
3547 conn->send[FIRSTSOCKET] = scp_send;
3548 }
3549 else {
3550 conn->recv[FIRSTSOCKET] = sftp_recv;
3551 conn->send[FIRSTSOCKET] = sftp_send;
3552 }
3553
3554 if(data->set.ssh_compression &&
3555 libssh2_session_flag(sshc->ssh_session, LIBSSH2_FLAG_COMPRESS, 1) < 0) {
3556 infof(data, "Failed to enable compression for ssh session");
3557 }
3558
3559 if(data->set.str[STRING_SSH_KNOWNHOSTS]) {
3560 int rc;
3561 sshc->kh = libssh2_knownhost_init(sshc->ssh_session);
3562 if(!sshc->kh) {
3563 libssh2_session_free(sshc->ssh_session);
3564 sshc->ssh_session = NULL;
3565 return CURLE_FAILED_INIT;
3566 }
3567
3568 /* read all known hosts from there */
3569 rc = libssh2_knownhost_readfile(sshc->kh,
3570 data->set.str[STRING_SSH_KNOWNHOSTS],
3571 LIBSSH2_KNOWNHOST_FILE_OPENSSH);
3572 if(rc < 0)
3573 infof(data, "Failed to read known hosts from %s",
3574 data->set.str[STRING_SSH_KNOWNHOSTS]);
3575 }
3576
3577#ifdef CURL_LIBSSH2_DEBUG
3578 libssh2_trace(sshc->ssh_session, ~0);
3579 infof(data, "SSH socket: %d", (int)sock);
3580#endif /* CURL_LIBSSH2_DEBUG */
3581
3582 myssh_to(data, sshc, SSH_INIT);
3583
3584 result = ssh_multi_statemach(data, done);
3585
3586 return result;
3587}
3588
3589/*
3590 ***********************************************************************
3591 *
3592 * scp_perform()
3593 *
3594 * This is the actual DO function for SCP. Get a file according to
3595 * the options previously setup.
3596 */
3597
3598static CURLcode scp_perform(struct Curl_easy *data,
3599 bool *connected,
3600 bool *dophase_done)
3601{
3602 struct ssh_conn *sshc = Curl_conn_meta_get(data->conn, CURL_META_SSH_CONN);
3603 CURLcode result = CURLE_OK;
3604
3605 CURL_TRC_SSH(data, "DO phase starts");
3606
3607 *dophase_done = FALSE; /* not done yet */
3608 if(!sshc)
3609 return CURLE_FAILED_INIT;
3610
3611 /* start the first command in the DO phase */
3612 myssh_to(data, sshc, SSH_SCP_TRANS_INIT);
3613
3614 /* run the state-machine */
3615 result = ssh_multi_statemach(data, dophase_done);
3616
3617 *connected = Curl_conn_is_connected(data->conn, FIRSTSOCKET);
3618
3619 if(*dophase_done) {
3620 CURL_TRC_SSH(data, "DO phase is complete");
3621 }
3622
3623 return result;
3624}
3625
3626/* called from multi.c while DOing */
3627static CURLcode scp_doing(struct Curl_easy *data,
3628 bool *dophase_done)
3629{
3630 CURLcode result;
3631 result = ssh_multi_statemach(data, dophase_done);
3632
3633 if(*dophase_done) {
3634 CURL_TRC_SSH(data, "DO phase is complete");
3635 }
3636 return result;
3637}
3638
3639/* BLOCKING, but the function is using the state machine so the only reason
3640 this is still blocking is that the multi interface code has no support for
3641 disconnecting operations that takes a while */
3642static CURLcode scp_disconnect(struct Curl_easy *data,
3643 struct connectdata *conn,
3644 bool dead_connection)
3645{
3646 CURLcode result = CURLE_OK;
3647 struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
3648 struct SSHPROTO *sshp = Curl_meta_get(data, CURL_META_SSH_EASY);
3649 (void)dead_connection;
3650
3651 if(sshc && sshc->ssh_session) {
3652 /* only if there is a session still around to use! */
3653 myssh_to(data, sshc, SSH_SESSION_DISCONNECT);
3654 result = ssh_block_statemach(data, sshc, sshp, TRUE);
3655 }
3656
3657 if(sshc)
3658 return sshc_cleanup(sshc, data, TRUE);
3659 return result;
3660}
3661
3662/* generic done function for both SCP and SFTP called from their specific
3663 done functions */
3664static CURLcode ssh_done(struct Curl_easy *data, CURLcode status)
3665{
3666 struct ssh_conn *sshc = Curl_conn_meta_get(data->conn, CURL_META_SSH_CONN);
3667 struct SSHPROTO *sshp = Curl_meta_get(data, CURL_META_SSH_EASY);
3668 CURLcode result = CURLE_OK;
3669
3670 if(!sshc || !sshp)
3671 return CURLE_FAILED_INIT;
3672
3673 if(!status)
3674 /* run the state-machine */
3675 result = ssh_block_statemach(data, sshc, sshp, FALSE);
3676 else
3677 result = status;
3678
3679 if(Curl_pgrsDone(data))
3680 return CURLE_ABORTED_BY_CALLBACK;
3681
3682 CURL_REQ_CLEAR_IO(data);
3683 return result;
3684}
3685
3686static CURLcode scp_done(struct Curl_easy *data, CURLcode status,
3687 bool premature)
3688{
3689 struct ssh_conn *sshc = Curl_conn_meta_get(data->conn, CURL_META_SSH_CONN);
3690 (void)premature;
3691
3692 if(sshc && !status)
3693 myssh_to(data, sshc, SSH_SCP_DONE);
3694
3695 return ssh_done(data, status);
3696}
3697
3698static CURLcode scp_send(struct Curl_easy *data, int sockindex,
3699 const uint8_t *mem, size_t len, bool eos,
3700 size_t *pnwritten)
3701{
3702 struct connectdata *conn = data->conn;
3703 struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
3704 CURLcode result = CURLE_OK;
3705 ssize_t nwritten;
3706
3707 (void)sockindex; /* we only support SCP on the fixed known primary socket */
3708 (void)eos;
3709 *pnwritten = 0;
3710
3711 if(!sshc)
3712 return CURLE_FAILED_INIT;
3713
3714 /* libssh2_channel_write() returns int! */
3715 nwritten = (ssize_t)libssh2_channel_write(sshc->ssh_channel,
3716 (const char *)mem, len);
3717
3718 ssh_block2waitfor(data, sshc, (nwritten == LIBSSH2_ERROR_EAGAIN));
3719
3720 if(nwritten == LIBSSH2_ERROR_EAGAIN)
3721 result = CURLE_AGAIN;
3722 else if(nwritten < LIBSSH2_ERROR_NONE)
3723 result = libssh2_session_error_to_CURLE((int)nwritten);
3724 else
3725 *pnwritten = (size_t)nwritten;
3726
3727 return result;
3728}
3729
3730static CURLcode scp_recv(struct Curl_easy *data, int sockindex,
3731 char *mem, size_t len, size_t *pnread)
3732{
3733 struct connectdata *conn = data->conn;
3734 struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
3735 CURLcode result = CURLE_OK;
3736 ssize_t nread;
3737
3738 (void)sockindex; /* we only support SCP on the fixed known primary socket */
3739 *pnread = 0;
3740
3741 if(!sshc)
3742 return CURLE_FAILED_INIT;
3743
3744 /* libssh2_channel_read() returns int */
3745 nread = (ssize_t)libssh2_channel_read(sshc->ssh_channel, mem, len);
3746
3747 ssh_block2waitfor(data, sshc, (nread == LIBSSH2_ERROR_EAGAIN));
3748 if(nread == LIBSSH2_ERROR_EAGAIN)
3749 return CURLE_AGAIN;
3750 else if(nread < LIBSSH2_ERROR_NONE)
3751 result = libssh2_session_error_to_CURLE((int)nread);
3752 else
3753 *pnread = (size_t)nread;
3754
3755 return result;
3756}
3757
3758/*
3759 * =============== SFTP ===============
3760 */
3761
3762/*
3763 ***********************************************************************
3764 *
3765 * sftp_perform()
3766 *
3767 * This is the actual DO function for SFTP. Get a file/directory according to
3768 * the options previously setup.
3769 */
3770
3771static CURLcode sftp_perform(struct Curl_easy *data,
3772 bool *connected,
3773 bool *dophase_done)
3774{
3775 struct ssh_conn *sshc = Curl_conn_meta_get(data->conn, CURL_META_SSH_CONN);
3776 CURLcode result = CURLE_OK;
3777
3778 CURL_TRC_SSH(data, "DO phase starts");
3779
3780 *dophase_done = FALSE; /* not done yet */
3781 if(!sshc)
3782 return CURLE_FAILED_INIT;
3783
3784 /* start the first command in the DO phase */
3785 myssh_to(data, sshc, SSH_SFTP_QUOTE_INIT);
3786
3787 /* run the state-machine */
3788 result = ssh_multi_statemach(data, dophase_done);
3789
3790 *connected = Curl_conn_is_connected(data->conn, FIRSTSOCKET);
3791
3792 if(*dophase_done) {
3793 CURL_TRC_SSH(data, "DO phase is complete");
3794 }
3795
3796 return result;
3797}
3798
3799/* called from multi.c while DOing */
3800static CURLcode sftp_doing(struct Curl_easy *data,
3801 bool *dophase_done)
3802{
3803 CURLcode result = ssh_multi_statemach(data, dophase_done);
3804
3805 if(*dophase_done) {
3806 CURL_TRC_SSH(data, "DO phase is complete");
3807 }
3808 return result;
3809}
3810
3811/* BLOCKING, but the function is using the state machine so the only reason
3812 this is still blocking is that the multi interface code has no support for
3813 disconnecting operations that takes a while */
3814static CURLcode sftp_disconnect(struct Curl_easy *data,
3815 struct connectdata *conn, bool dead_connection)
3816{
3817 CURLcode result = CURLE_OK;
3818 struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
3819 struct SSHPROTO *sshp = Curl_meta_get(data, CURL_META_SSH_EASY);
3820 (void)dead_connection;
3821
3822 if(sshc) {
3823 if(sshc->ssh_session) {
3824 /* only if there is a session still around to use! */
3825 CURL_TRC_SSH(data, "DISCONNECT starts now");
3826 myssh_to(data, sshc, SSH_SFTP_SHUTDOWN);
3827 result = ssh_block_statemach(data, sshc, sshp, TRUE);
3828 CURL_TRC_SSH(data, "DISCONNECT is done -> %d", result);
3829 }
3830 sshc_cleanup(sshc, data, TRUE);
3831 }
3832 return result;
3833}
3834
3835static CURLcode sftp_done(struct Curl_easy *data, CURLcode status,
3836 bool premature)
3837{
3838 struct connectdata *conn = data->conn;
3839 struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
3840
3841 if(!sshc)
3842 return CURLE_FAILED_INIT;
3843
3844 if(!status) {
3845 /* Post quote commands are executed after the SFTP_CLOSE state to avoid
3846 errors that could happen due to open file handles during POSTQUOTE
3847 operation */
3848 if(!premature && data->set.postquote && !conn->bits.retry)
3849 sshc->nextstate = SSH_SFTP_POSTQUOTE_INIT;
3850 myssh_to(data, sshc, SSH_SFTP_CLOSE);
3851 }
3852 return ssh_done(data, status);
3853}
3854
3855/* return number of sent bytes */
3856static CURLcode sftp_send(struct Curl_easy *data, int sockindex,
3857 const uint8_t *mem, size_t len, bool eos,
3858 size_t *pnwritten)
3859{
3860 struct connectdata *conn = data->conn;
3861 struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
3862 ssize_t nwrite;
3863
3864 (void)sockindex;
3865 (void)eos;
3866 *pnwritten = 0;
3867
3868 if(!sshc)
3869 return CURLE_FAILED_INIT;
3870
3871 nwrite = libssh2_sftp_write(sshc->sftp_handle, (const char *)mem, len);
3872
3873 ssh_block2waitfor(data, sshc, (nwrite == LIBSSH2_ERROR_EAGAIN));
3874
3875 if(nwrite == LIBSSH2_ERROR_EAGAIN)
3876 return CURLE_AGAIN;
3877 else if(nwrite < LIBSSH2_ERROR_NONE)
3878 return libssh2_session_error_to_CURLE((int)nwrite);
3879 *pnwritten = (size_t)nwrite;
3880 return CURLE_OK;
3881}
3882
3883/*
3884 * Return number of received (decrypted) bytes
3885 * or <0 on error
3886 */
3887static CURLcode sftp_recv(struct Curl_easy *data, int sockindex,
3888 char *mem, size_t len, size_t *pnread)
3889{
3890 struct connectdata *conn = data->conn;
3891 struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
3892 ssize_t nread;
3893
3894 (void)sockindex;
3895 *pnread = 0;
3896
3897 if(!sshc)
3898 return CURLE_FAILED_INIT;
3899
3900 nread = libssh2_sftp_read(sshc->sftp_handle, mem, len);
3901
3902 ssh_block2waitfor(data, sshc, (nread == LIBSSH2_ERROR_EAGAIN));
3903
3904 if(nread == LIBSSH2_ERROR_EAGAIN)
3905 return CURLE_AGAIN;
3906 else if(nread < 0)
3907 return libssh2_session_error_to_CURLE((int)nread);
3908
3909 *pnread = (size_t)nread;
3910 return CURLE_OK;
3911}
3912
3913/*
3914 * The DO function is generic for both protocols. There was previously two
3915 * separate ones but this way means less duplicated code.
3916 */
3917static CURLcode ssh_do(struct Curl_easy *data, bool *done)
3918{
3919 CURLcode result;
3920 bool connected = FALSE;
3921 struct connectdata *conn = data->conn;
3922 struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
3923
3924 *done = FALSE; /* default to false */
3925 if(!sshc)
3926 return CURLE_FAILED_INIT;
3927
3928 data->req.size = -1; /* make sure this is unknown at this point */
3929 sshc->secondCreateDirs = 0; /* reset the create directory attempt state
3930 variable */
3931
3932 Curl_pgrsReset(data);
3933
3934 if(conn->scheme->protocol & CURLPROTO_SCP)
3935 result = scp_perform(data, &connected, done);
3936 else
3937 result = sftp_perform(data, &connected, done);
3938
3939 return result;
3940}
3941
3942CURLcode Curl_ssh_init(void)
3943{
3944 if(libssh2_init(0)) {
3945 DEBUGF(curl_mfprintf(stderr, "Error: libssh2_init failed\n"));
3946 return CURLE_FAILED_INIT;
3947 }
3948 return CURLE_OK;
3949}
3950
3951void Curl_ssh_cleanup(void)
3952{
3953 libssh2_exit();
3954}
3955
3956void Curl_ssh_version(char *buffer, size_t buflen)
3957{
3958 (void)curl_msnprintf(buffer, buflen, "libssh2/%s", libssh2_version(0));
3959}
3960
3961/* The SSH session is associated with the *CONNECTION* but the callback user
3962 * pointer is an easy handle pointer. This function allows us to reassign the
3963 * user pointer to the *CURRENT* (new) easy handle.
3964 */
3965static void ssh_attach(struct Curl_easy *data, struct connectdata *conn)
3966{
3967 DEBUGASSERT(data);
3968 DEBUGASSERT(conn);
3969 if(conn->scheme->protocol & PROTO_FAMILY_SSH) {
3970 struct ssh_conn *sshc = Curl_conn_meta_get(conn, CURL_META_SSH_CONN);
3971 if(sshc && sshc->ssh_session) {
3972 /* only re-attach if the session already exists */
3973 void **abstract = libssh2_session_abstract(sshc->ssh_session);
3974 *abstract = data;
3975 }
3976 }
3977}
3978
3979/*
3980 * SCP protocol handler.
3981 */
3982const struct Curl_protocol Curl_protocol_scp = {
3983 ssh_setup_connection, /* setup_connection */
3984 ssh_do, /* do_it */
3985 scp_done, /* done */
3986 ZERO_NULL, /* do_more */
3987 ssh_connect, /* connect_it */
3988 ssh_multi_statemach, /* connecting */
3989 scp_doing, /* doing */
3990 ssh_pollset, /* proto_pollset */
3991 ssh_pollset, /* doing_pollset */
3992 ZERO_NULL, /* domore_pollset */
3993 ssh_pollset, /* perform_pollset */
3994 scp_disconnect, /* disconnect */
3995 ZERO_NULL, /* write_resp */
3996 ZERO_NULL, /* write_resp_hd */
3997 ZERO_NULL, /* connection_is_dead */
3998 ssh_attach, /* attach */
3999 ZERO_NULL, /* follow */
4000};
4001
4002/*
4003 * SFTP protocol handler.
4004 */
4005const struct Curl_protocol Curl_protocol_sftp = {
4006 ssh_setup_connection, /* setup_connection */
4007 ssh_do, /* do_it */
4008 sftp_done, /* done */
4009 ZERO_NULL, /* do_more */
4010 ssh_connect, /* connect_it */
4011 ssh_multi_statemach, /* connecting */
4012 sftp_doing, /* doing */
4013 ssh_pollset, /* proto_pollset */
4014 ssh_pollset, /* doing_pollset */
4015 ZERO_NULL, /* domore_pollset */
4016 ssh_pollset, /* perform_pollset */
4017 sftp_disconnect, /* disconnect */
4018 ZERO_NULL, /* write_resp */
4019 ZERO_NULL, /* write_resp_hd */
4020 ZERO_NULL, /* connection_is_dead */
4021 ssh_attach, /* attach */
4022 ZERO_NULL, /* follow */
4023};
4024
4025#endif /* USE_LIBSSH2 */