SMB: drop support
No binary (build failed)
—
(log yok)
| @@ -45,9 +45,7 @@ commands: | |
| steps: | |
| - run: | |
| command: | | |
| - | sudo apt-get update && sudo apt-get install -y libpsl-dev libbrotli-dev libzstd-dev zlib1g-dev python3-pip |
| - | python3 -m venv ~/venv |
| - | ~/venv/bin/pip --disable-pip-version-check --no-input --no-cache-dir install --progress-bar off --prefer-binary -r tests/requirements.txt |
| + | sudo apt-get update && sudo apt-get install -y libpsl-dev libbrotli-dev libzstd-dev zlib1g-dev |
| configure: | |
| steps: | |
| @@ -104,7 +102,6 @@ commands: | |
| steps: | |
| - run: | |
| command: | | |
| - | source ~/venv/bin/activate |
| # Revert a CircleCI-specific local setting that makes test 1459 | |
| # return 67 (CURLE_LOGIN_DENIED) instead of the | |
| # expected 60 (CURLE_PEER_FAILED_VERIFICATION). | |
| @@ -454,14 +454,6 @@ script: | |
| scripts/**\ | |
| }" | |
| - | SMB: |
| - | - all: |
| - | - changed-files: |
| - | - any-glob-to-all-files: "{\ |
| - | lib/smb.*,\ |
| - | tests/smbserver.py\ |
| - | }" |
| - | |
| SMTP: | |
| - all: | |
| - changed-files: | |
| @@ -792,9 +792,7 @@ slist | |
| sln | |
| Slowloris | |
| SMB | |
| - | smb |
| SMBS | |
| - | smbs |
| SMBv | |
| SMTP | |
| smtp | |
| @@ -80,7 +80,6 @@ jobs: | |
| pip: | | |
| -r .github/scripts/requirements.txt | |
| -r tests/http/requirements.txt | |
| - | -r tests/requirements.txt |
| - name: 'REUSE check' | |
| background: true | |
| @@ -142,7 +141,6 @@ jobs: | |
| pytype==2024.10.11 | |
| -r .github/scripts/requirements.txt | |
| -r tests/http/requirements.txt | |
| - | -r tests/requirements.txt |
| - name: 'check' | |
| run: | | |
| @@ -840,21 +840,12 @@ jobs: | |
| make -C bld V=1 -C tests | |
| fi | |
| - | - name: 'install test prereqs' |
| - | if: ${{ !contains(matrix.build.install_steps, 'skipall') && !contains(matrix.build.install_steps, 'skiprun') }} |
| - | run: | |
| - | python3 -m venv ~/venv |
| - | if bld/src/curl --disable -V 2>/dev/null | grep smb; then |
| - | ~/venv/bin/pip --disable-pip-version-check --no-input --no-cache-dir install --progress-bar off --prefer-binary -r tests/requirements.txt |
| - | fi |
| - | |
| - name: 'run tests' | |
| if: ${{ !contains(matrix.build.install_steps, 'skipall') && !contains(matrix.build.install_steps, 'skiprun') }} | |
| env: | |
| TFLAGS: '${{ matrix.build.tflags }}' | |
| run: | | |
| TFLAGS+=' -n' | |
| - | source ~/venv/bin/activate |
| if [ "${MATRIX_BUILD}" = 'cmake' ]; then | |
| cmake --build bld --verbose --target test-ci | |
| else | |
| @@ -865,7 +856,6 @@ jobs: | |
| if: ${{ !contains(matrix.build.install_steps, 'skipall') && !contains(matrix.build.install_steps, 'skiprun') }} | |
| run: | | |
| export TFLAGS='-j6 --min=4 HTTP/3' | |
| - | source ~/venv/bin/activate |
| if [ "${MATRIX_BUILD}" = 'cmake' ]; then | |
| cmake --build bld --verbose --target test-ci | |
| else | |
| @@ -78,7 +78,7 @@ jobs: | |
| - name: 'awslc' | |
| install_steps: awslc pytest | |
| LDFLAGS: -Wl,-rpath,/home/runner/awslc/lib | |
| - | configure: --with-openssl=/home/runner/awslc --enable-ech --enable-ntlm --enable-smb |
| + | configure: --with-openssl=/home/runner/awslc --enable-ech --enable-ntlm |
| - name: 'awslc' | |
| install_packages: libidn2-dev | |
| @@ -271,7 +271,7 @@ jobs: | |
| - name: 'openssl !ipv6 !--libcurl !--digest-auth' | |
| image: ubuntu-24.04-arm | |
| - | configure: --with-openssl --disable-ipv6 --enable-debug --disable-unity --disable-libcurl-option --disable-digest-auth --enable-ntlm --enable-smb |
| + | configure: --with-openssl --disable-ipv6 --enable-debug --disable-unity --disable-libcurl-option --disable-digest-auth --enable-ntlm |
| - name: 'curl_global_init_mem debug valgrind' | |
| image: ubuntu-24.04-arm | |
| @@ -280,7 +280,7 @@ jobs: | |
| configure: >- | |
| --enable-init-mem-debug | |
| --with-openssl --disable-debug --enable-unity | |
| - | --enable-ntlm --enable-smb |
| + | --enable-ntlm |
| - name: 'openssl https-only' | |
| image: ubuntu-24.04-arm | |
| @@ -291,7 +291,7 @@ jobs: | |
| --disable-imap --disable-pop3 --disable-smtp | |
| --disable-rtsp | |
| --without-libssh2 --without-libssh | |
| - | --disable-tftp --disable-ftp --disable-file --disable-smb |
| + | --disable-tftp --disable-ftp --disable-file |
| --enable-ntlm | |
| - name: 'openssl torture 1' | |
| @@ -433,7 +433,7 @@ jobs: | |
| - name: 'event-based' | |
| install_packages: libssh-dev | |
| - | configure: --enable-debug --enable-static --disable-shared --disable-threaded-resolver --with-libssh --with-openssl --enable-ntlm --enable-smb |
| + | configure: --enable-debug --enable-static --disable-shared --disable-threaded-resolver --with-libssh --with-openssl --enable-ntlm |
| tflags: '-n --test-event --min=1420' | |
| - name: 'duphandle' | |
| @@ -926,14 +926,6 @@ jobs: | |
| make -C bld V=1 -C tests | |
| fi | |
| - | - name: 'install test prereqs' |
| - | if: ${{ !contains(matrix.build.install_steps, 'skipall') && !contains(matrix.build.install_steps, 'skiprun') && matrix.build.container == null }} |
| - | run: | |
| - | python3 -m venv ~/venv |
| - | if bld/src/curl --disable -V 2>/dev/null | grep smb; then |
| - | ~/venv/bin/pip --disable-pip-version-check --no-input --no-cache-dir install --progress-bar off --prefer-binary -r tests/requirements.txt |
| - | fi |
| - | |
| - name: 'run tests' | |
| if: ${{ !contains(matrix.build.install_steps, 'skipall') && !contains(matrix.build.install_steps, 'skiprun') }} | |
| timeout-minutes: ${{ contains(matrix.build.install_packages, 'valgrind') && 20 || 10 }} | |
| @@ -544,14 +544,6 @@ jobs: | |
| make -C bld V=1 -C tests | |
| fi | |
| - | - name: 'install test prereqs' |
| - | if: ${{ !contains(matrix.build.install_steps, 'skipall') && !contains(matrix.build.install_steps, 'skiprun') }} |
| - | run: | |
| - | python3 -m venv ~/venv |
| - | if bld/src/curl --disable -V 2>/dev/null | grep smb; then |
| - | ~/venv/bin/pip --disable-pip-version-check --no-input --no-cache-dir install --progress-bar off --prefer-binary -r tests/requirements.txt |
| - | fi |
| - | |
| - name: 'run tests' | |
| if: ${{ !contains(matrix.build.install_steps, 'skipall') && !contains(matrix.build.install_steps, 'skiprun') }} | |
| timeout-minutes: ${{ contains(matrix.build.install_steps, 'torture') && 20 || 10 }} | |
| @@ -563,7 +555,6 @@ jobs: | |
| if [ "${TEST_TARGET}" != 'test-ci' ]; then | |
| TFLAGS+=' --buildinfo' # only test-ci sets this by default, set it manually for test-torture | |
| fi | |
| - | source ~/venv/bin/activate |
| if [[ "${MATRIX_INSTALL_STEPS}" = *'codeset-test1'* ]]; then | |
| locale || true | |
| unset LANG | |
| @@ -767,14 +767,6 @@ jobs: | |
| key: ${{ runner.os }}-stunnel-${{ env.STUNNEL_VERSION }}-amd64 | |
| fail-on-cache-miss: true | |
| - | - name: 'install test prereqs' |
| - | if: ${{ matrix.tflags != 'skipall' && matrix.tflags != 'skiprun' }} |
| - | timeout-minutes: 2 |
| - | run: | |
| - | if bld/src/curl.exe --disable -V 2>/dev/null | grep smb; then |
| - | python3 -m pip --disable-pip-version-check --no-input --no-cache-dir install --progress-bar off --prefer-binary -r tests/requirements.txt |
| - | fi |
| - | |
| - name: 'run tests' | |
| if: ${{ matrix.tflags != 'skipall' && matrix.tflags != 'skiprun' }} | |
| timeout-minutes: 10 | |
| @@ -1003,8 +995,6 @@ jobs: | |
| image: 'windows-11-arm' | |
| openssh: 'OpenSSH-Windows' | |
| tflags: '--min=1720' | |
| - | # leave SMB disabled to save 30-60 seconds by omitting prereqs, |
| - | # to counteract the slower test run step |
| config: >- | |
| -DENABLE_DEBUG=ON | |
| -DCURL_USE_SCHANNEL=ON | |
| @@ -1204,9 +1194,6 @@ jobs: | |
| sha256sum pkg.bin && sha256sum pkg.bin | grep -qwF -- "${OPENSSH_WINDOWS_SHA256_WIN64}" && unzip pkg.bin && rm -f pkg.bin | |
| fi | |
| fi | |
| - | if "bld/src/${MATRIX_TYPE}/curl.exe" --disable -V 2>/dev/null | grep smb; then |
| - | python3 -m pip --disable-pip-version-check --no-input --no-cache-dir install --progress-bar off --prefer-binary -r tests/requirements.txt |
| - | fi |
| - name: 'run tests' | |
| if: ${{ matrix.tflags != 'skipall' && matrix.tflags != 'skiprun' }} | |
| @@ -498,8 +498,6 @@ option(CURL_DISABLE_SHA512_256 "Disable SHA-512/256 hash algorithm" OFF) | |
| mark_as_advanced(CURL_DISABLE_SHA512_256) | |
| option(CURL_DISABLE_SHUFFLE_DNS "Disable shuffle DNS feature" OFF) | |
| mark_as_advanced(CURL_DISABLE_SHUFFLE_DNS) | |
| - | option(CURL_ENABLE_SMB "Enable SMB" OFF) |
| - | mark_as_advanced(CURL_ENABLE_SMB) |
| option(CURL_DISABLE_SMTP "Disable SMTP" OFF) | |
| mark_as_advanced(CURL_DISABLE_SMTP) | |
| option(CURL_DISABLE_SOCKETPAIR "Disable use of socketpair for curl_multi_poll()" OFF) | |
| @@ -1992,10 +1990,6 @@ curl_add_if("POP3" NOT CURL_DISABLE_POP3) | |
| curl_add_if("POP3S" NOT CURL_DISABLE_POP3 AND _ssl_enabled) | |
| curl_add_if("IMAP" NOT CURL_DISABLE_IMAP) | |
| curl_add_if("IMAPS" NOT CURL_DISABLE_IMAP AND _ssl_enabled) | |
| - | curl_add_if("SMB" CURL_ENABLE_SMB AND |
| - | _use_curl_ntlm_core AND (SIZEOF_CURL_OFF_T GREATER 4)) |
| - | curl_add_if("SMBS" CURL_ENABLE_SMB AND _ssl_enabled AND |
| - | _use_curl_ntlm_core AND (SIZEOF_CURL_OFF_T GREATER 4)) |
| curl_add_if("SMTP" NOT CURL_DISABLE_SMTP) | |
| curl_add_if("SMTPS" NOT CURL_DISABLE_SMTP AND _ssl_enabled) | |
| curl_add_if("SCP" USE_LIBSSH2 OR USE_LIBSSH) | |
| @@ -9,7 +9,7 @@ SPDX-License-Identifier: curl | |
| curl is a command-line tool for transferring data from or to a server using | |
| URLs. It supports these protocols: DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, | |
| HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, MQTTS, POP3, POP3S, RTSP, SCP, | |
| - | SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS. |
| + | SFTP, SMTP, SMTPS, TELNET, TFTP, WS and WSS. |
| Learn how to use curl by reading [the | |
| man page](https://curl.se/docs/manpage.html) or [everything | |
| @@ -85,7 +85,6 @@ Planned upcoming removals include: | |
| o HTTP/2 Server Push | |
| o local crypto implementations | |
| o NTLM | |
| - | o SMB |
| See https://curl.se/dev/deprecate.html | |
| @@ -1058,23 +1058,6 @@ AS_HELP_STRING([--disable-imap],[Disable IMAP support]), | |
| AC_MSG_RESULT(yes) | |
| ) | |
| - | AC_MSG_CHECKING([whether to support smb]) |
| - | AC_ARG_ENABLE(smb, |
| - | AS_HELP_STRING([--enable-smb],[Enable SMB support]) |
| - | AS_HELP_STRING([--disable-smb],[Disable SMB support]), |
| - | [ case "$enableval" in |
| - | yes) |
| - | AC_MSG_RESULT(yes) |
| - | AC_DEFINE(CURL_ENABLE_SMB, 1, [to enable SMB]) |
| - | CURL_ENABLE_SMB=1 |
| - | ;; |
| - | *) |
| - | AC_MSG_RESULT(no) |
| - | ;; |
| - | esac ], |
| - | AC_MSG_RESULT(no) |
| - | ) |
| - | |
| AC_MSG_CHECKING([whether to support smtp]) | |
| AC_ARG_ENABLE(smtp, | |
| AS_HELP_STRING([--enable-smtp],[Enable SMTP support]) | |
| @@ -5477,12 +5460,6 @@ if test "$CURL_DISABLE_IMAP" != "1"; then | |
| SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS IMAPS" | |
| fi | |
| fi | |
| - | if test "$CURL_ENABLE_SMB" = "1" && test "$use_curl_ntlm_core" = "yes"; then |
| - | SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS SMB" |
| - | if test "$SSL_ENABLED" = "1"; then |
| - | SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS SMBS" |
| - | fi |
| - | fi |
| if test "$CURL_DISABLE_SMTP" != "1"; then | |
| SUPPORT_PROTOCOLS="$SUPPORT_PROTOCOLS SMTP" | |
| if test "$SSL_ENABLED" = "1"; then | |
| @@ -161,10 +161,6 @@ Disable the SHA-512/256 hash algorithm. | |
| Disable the shuffle DNS feature | |
| - | ## `CURL_ENABLE_SMB` |
| - | |
| - | Enable the SMB(S) protocols |
| - | |
| ## `CURL_DISABLE_SMTP` | |
| Disable the SMTP(S) protocols | |
| @@ -22,7 +22,7 @@ The curl project produces two products: | |
| A client-side URL transfer library, supporting DICT, FILE, FTP, FTPS, GOPHER, | |
| GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, MQTT, MQTTS, POP3, POP3S, | |
| - | RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS. |
| + | RTSP, SCP, SFTP, SMTP, SMTPS, TELNET, TFTP, WS and WSS. |
| libcurl supports HTTPS certificates, HTTP POST, HTTP PUT, FTP uploading, | |
| Kerberos, SPNEGO, HTTP form based upload, proxies, cookies, user+password | |
| @@ -184,13 +184,6 @@ SPDX-License-Identifier: curl | |
| - upload | |
| - resume | |
| - | ## SMB |
| - | |
| - | - SMBv1 over TCP and SSL |
| - | - download |
| - | - upload |
| - | - authentication with NTLMv1 |
| - | |
| ## SMTP | |
| - authentication: Plain, Login, CRAM-MD5, Digest-MD5, NTLM, Kerberos 5 and | |
| @@ -503,3 +503,5 @@ December 15: the website served 78 TB over the last month. | |
| ## 2026 | |
| April: removed support for RTMP | |
| + | |
| + | September: removed support for SMB |
| @@ -246,7 +246,6 @@ target_link_libraries(my_target PRIVATE CURL::libcurl) | |
| - `CURL_ENABLE_APPLE_FAST_UDP`: Use Apple fast UDP (experimental). Default: `OFF` | |
| - `CURL_ENABLE_NTLM`: Enable NTLM support. Default: `OFF` | |
| - | - `CURL_ENABLE_SMB`: Enable SMB. Default: `OFF` |
| - `CURL_ENABLE_SSL`: Enable SSL support. Default: `ON` | |
| - `CURL_WINDOWS_SSPI`: Enable SSPI on Windows. Default: =`CURL_USE_SCHANNEL` | |
| - `ENABLE_IPV6`: Enable IPv6 support. Default: `ON` if target supports IPv6. | |
| @@ -63,10 +63,6 @@ Get the main page from an IPv6 web server: | |
| curl "http://[2001:1890:1112:1::20]/" | |
| - | Get a file from an SMB server: |
| - | |
| - | curl -u "domain\username:passwd" smb://server.example.com/share/file.txt |
| - | |
| ## Download to a File | |
| Get a webpage and store in a local file with a specific name: | |
| @@ -244,11 +240,6 @@ fashion similar to: | |
| curl --proxytunnel -x proxy:port -T localfile ftp.example.com | |
| - | ### SMB / SMBS |
| - | |
| - | curl -T file.txt -u "domain\username:passwd" |
| - | smb://server.example.com/share/ |
| - | |
| ### HTTP | |
| Upload all data on stdin to a specified HTTPS site: | |
| @@ -930,13 +930,6 @@ http operations (for which we have test servers). | |
| Make the test suite work on more platforms. OpenBSD and macOS. Remove fork()s | |
| and it should become even more portable. | |
| - | ## write an SMB test server to replace impacket |
| - | |
| - | This would allow us to run SMB tests on more platforms and do better and more |
| - | covering tests. |
| - | |
| - | See [curl issue 15697](https://github.com/curl/curl/issues/15697) |
| - | |
| ## Use the RFC 6265 test suite | |
| A test suite made for HTTP cookies (RFC 6265) by Adam Barth [is | |
| @@ -141,8 +141,8 @@ curl supports the following schemes on URLs specified to transfer. They are | |
| matched case insensitively: | |
| `dict`, `file`, `ftp`, `ftps`, `gopher`, `gophers`, `http`, `https`, `imap`, | |
| - | `imaps`, `ldap`, `ldaps`, `mqtt`, `pop3`, `pop3s`, `rtsp`, `smb`, `smbs`, |
| - | `smtp`, `smtps`, `telnet`, `tftp` |
| + | `imaps`, `ldap`, `ldaps`, `mqtt`, `pop3`, `pop3s`, `rtsp`, `smtp`, `smtps`, |
| + | `telnet`, `tftp` |
| When the URL is specified to identify a proxy, curl recognizes the following | |
| schemes: | |
| @@ -243,7 +243,7 @@ number based on the provide scheme: | |
| DICT 2628, FTP 21, FTPS 990, GOPHER 70, GOPHERS 70, HTTP 80, HTTPS 443, IMAP | |
| 143, IMAPS 993, LDAP 389, LDAPS 636, MQTT 1883, POP3 110, POP3S 995, RTSP 554, | |
| - | SCP 22, SFTP 22, SMB 445, SMBS 445, SMTP 25, SMTPS 465, TELNET 23, TFTP 69 |
| + | SCP 22, SFTP 22, SMTP 25, SMTPS 465, TELNET 23, TFTP 69 |
| ## Path | |
| @@ -398,17 +398,6 @@ path ends with a slash (`/`) then a directory listing is returned instead of a | |
| file. If the path is omitted entirely then the directory listing for the root | |
| / home directory is returned. | |
| - | ## SMB |
| - | The path part of an SMB request specifies the file to retrieve and from what |
| - | share and directory or the share to upload to and as such, may not be omitted. |
| - | If the username is embedded in the URL then it must contain the domain name |
| - | and as such, the backslash must be URL encoded as %2f. |
| - | |
| - | When uploading to SMB, the size of the file needs to be known ahead of time, |
| - | meaning that you can upload a file passed to curl over a pipe like stdin. |
| - | |
| - | curl supports SMB version 1 (only) |
| - | |
| ## SMTP | |
| The path part of an SMTP request specifies the hostname to present during | |
| @@ -4,8 +4,8 @@ | |
| **curl** is a tool for transferring data from or to a server using URLs. It | |
| supports these protocols: DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, | |
| - | IMAP, IMAPS, LDAP, LDAPS, MQTT, MQTTS, POP3, POP3S, RTSP, SCP, SFTP, SMB, |
| - | SMBS, SMTP, SMTPS, TELNET, TFTP, WS and WSS. |
| + | IMAP, IMAPS, LDAP, LDAPS, MQTT, MQTTS, POP3, POP3S, RTSP, SCP, SFTP, SMTP, |
| + | SMTPS, TELNET, TFTP, WS and WSS. |
| curl is powered by libcurl for all transfer-related features. See | |
| *libcurl(3)* for details. | |
| @@ -36,8 +36,6 @@ curl supports RTSP 1.0 downloads. | |
| curl supports SSH version 2 scp transfers. | |
| ## SFTP | |
| curl supports SFTP (draft 5) done over SSH version 2. | |
| - | ## SMB(S) |
| - | curl supports SMB version 1 for upload and download. |
| ## SMTP(S) | |
| Uploading contents to an SMTP server means sending an email. With or without | |
| TLS. | |
| @@ -40,8 +40,8 @@ CURLPROTO_GOPHER, CURLPROTO_HTTP, CURLPROTO_HTTPS, CURLPROTO_IMAP, | |
| CURLPROTO_IMAPS, CURLPROTO_LDAP, CURLPROTO_LDAPS, CURLPROTO_POP3, | |
| CURLPROTO_POP3S, CURLPROTO_RTMP, CURLPROTO_RTMPE, CURLPROTO_RTMPS, | |
| CURLPROTO_RTMPT, CURLPROTO_RTMPTE, CURLPROTO_RTMPTS, CURLPROTO_RTSP, | |
| - | CURLPROTO_SCP, CURLPROTO_SFTP, CURLPROTO_SMB, CURLPROTO_SMBS, CURLPROTO_SMTP, |
| - | CURLPROTO_SMTPS, CURLPROTO_TELNET, CURLPROTO_TFTP, CURLPROTO_MQTT |
| + | CURLPROTO_SCP, CURLPROTO_SFTP, CURLPROTO_SMTP, CURLPROTO_SMTPS, |
| + | CURLPROTO_TELNET, CURLPROTO_TFTP, CURLPROTO_MQTT |
| ~~~ | |
| # %PROTOCOLS% | |
| @@ -35,7 +35,7 @@ name. | |
| Use one of these protocol (scheme) names: | |
| dict, file, ftp, ftps, gopher, http, https, imap, imaps, ldap, ldaps, pop3, | |
| - | pop3s, rtsp, scp, sftp, smb, smbs, smtp, smtps, telnet, tftp |
| + | pop3s, rtsp, scp, sftp, smtp, smtps, telnet, tftp |
| An unknown or unsupported protocol causes error *CURLE_UNSUPPORTED_PROTOCOL* | |
| when libcurl parses a URL without a scheme. Parsing happens when | |
| @@ -12,7 +12,6 @@ Protocol: | |
| - FTP | |
| - SFTP | |
| - FILE | |
| - | - SMB |
| Added-in: 7.5 | |
| --- | |
| @@ -56,17 +56,9 @@ CURLPROTO_LDAPS | |
| CURLPROTO_MQTT | |
| CURLPROTO_POP3 | |
| CURLPROTO_POP3S | |
| - | CURLPROTO_RTMP |
| - | CURLPROTO_RTMPE |
| - | CURLPROTO_RTMPS |
| - | CURLPROTO_RTMPT |
| - | CURLPROTO_RTMPTE |
| - | CURLPROTO_RTMPTS |
| CURLPROTO_RTSP | |
| CURLPROTO_SCP | |
| CURLPROTO_SFTP | |
| - | CURLPROTO_SMB |
| - | CURLPROTO_SMBS |
| CURLPROTO_SMTP | |
| CURLPROTO_SMTPS | |
| CURLPROTO_TELNET | |
| @@ -42,8 +42,7 @@ set, it returns error. | |
| These are the available protocols: | |
| DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, | |
| - | MQTT, MQTTS, POP3, POP3S, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, |
| - | TFTP, WS, WSS |
| + | MQTT, MQTTS, POP3, POP3S, RTSP, SCP, SFTP, SMTP, SMTPS, TELNET, TFTP, WS, WSS |
| You can set "ALL" as a short-cut to enable all protocols. Note that by setting | |
| all, you may enable protocols that were not supported the day you write this | |
| @@ -87,6 +86,8 @@ int main(int argc, char *argv[]) | |
| RTMP and its related protocol schemes are not supported since curl 8.20.0 | |
| + | SMB and SMBS were removed in curl 8.23.0 |
| + | |
| # %AVAILABILITY% | |
| # RETURN VALUE | |
| @@ -61,17 +61,9 @@ CURLPROTO_LDAPS | |
| CURLPROTO_MQTT | |
| CURLPROTO_POP3 | |
| CURLPROTO_POP3S | |
| - | CURLPROTO_RTMP |
| - | CURLPROTO_RTMPE |
| - | CURLPROTO_RTMPS |
| - | CURLPROTO_RTMPT |
| - | CURLPROTO_RTMPTE |
| - | CURLPROTO_RTMPTS |
| CURLPROTO_RTSP | |
| CURLPROTO_SCP | |
| CURLPROTO_SFTP | |
| - | CURLPROTO_SMB |
| - | CURLPROTO_SMBS |
| CURLPROTO_SMTP | |
| CURLPROTO_SMTPS | |
| CURLPROTO_TELNET | |
| @@ -46,8 +46,7 @@ By default libcurl allows HTTP, HTTPS, FTP and FTPS on redirects (since | |
| These are the available protocols: | |
| DICT, FILE, FTP, FTPS, GOPHER, GOPHERS, HTTP, HTTPS, IMAP, IMAPS, LDAP, LDAPS, | |
| - | MQTT, MQTTS, POP3, POP3S, RTSP, SCP, SFTP, SMB, SMBS, SMTP, SMTPS, TELNET, |
| - | TFTP, WS, WSS |
| + | MQTT, MQTTS, POP3, POP3S, RTSP, SCP, SFTP, SMTP, SMTPS, TELNET, TFTP, WS, WSS |
| You can set "ALL" as a short-cut to enable all protocols. Note that by setting | |
| all, you may enable protocols that were not supported the day you write this | |
| @@ -89,6 +88,12 @@ int main(int argc, char *argv[]) | |
| } | |
| ~~~ | |
| + | # HISTORY |
| + | |
| + | RTMP and its related protocol schemes are not supported since curl 8.20.0 |
| + | |
| + | SMB and SMBS were removed in curl 8.23.0 |
| + | |
| # %AVAILABILITY% | |
| # RETURN VALUE | |
| @@ -992,8 +992,8 @@ CURLPROTO_RTMPTS 7.21.0 8.20.0 | |
| CURLPROTO_RTSP 7.20.0 | |
| CURLPROTO_SCP 7.19.4 | |
| CURLPROTO_SFTP 7.19.4 | |
| - | CURLPROTO_SMB 7.40.0 |
| - | CURLPROTO_SMBS 7.40.0 |
| + | CURLPROTO_SMB 7.40.0 8.23.0 |
| + | CURLPROTO_SMBS 7.40.0 8.23.0 |
| CURLPROTO_SMTP 7.20.0 | |
| CURLPROTO_SMTPS 7.20.0 | |
| CURLPROTO_TELNET 7.19.4 | |
| @@ -193,8 +193,6 @@ Available substitute variables include: | |
| - `%RESOLVE` - server/resolve command | |
| - `%RTSP6PORT` - IPv6 port number of the RTSP server | |
| - `%RTSPPORT` - Port number of the RTSP server | |
| - | - `%SMBPORT` - Port number of the SMB server |
| - | - `%SMBSPORT` - Port number of the SMBS server |
| - `%SMTP6PORT` - IPv6 port number of the SMTP server | |
| - `%SMTPPORT` - Port number of the SMTP server | |
| - `%SOCKSPORT` - Port number of the SOCKS4/5 server | |
| @@ -453,7 +451,6 @@ What server(s) this test case requires/uses. Available servers: | |
| - `rtsp-ipv6` | |
| - `scp` | |
| - `sftp` | |
| - | - `smb` |
| - `smtp` | |
| - `socks4` | |
| - `socks5` | |
| @@ -46,8 +46,7 @@ output from the servers used in the test. | |
| ## Requires to run | |
| - `perl` (and a Unix-style shell) | |
| - | - `python` (and a Unix-style shell, for SMB and TELNET tests) |
| - | - `python-impacket` (for SMB tests) |
| + | - `python` (and a Unix-style shell, for TELNET tests) |
| - `diff` (when a test fails, a diff is shown) | |
| - `stunnel` (for HTTPS and FTPS tests) | |
| - `openssl` (the command line tool, for generating test server certificates) | |
| @@ -274,7 +274,6 @@ LIB_CFILES = \ | |
| setopt.c \ | |
| sha256.c \ | |
| slist.c \ | |
| - | smb.c \ |
| smtp.c \ | |
| socketpair.c \ | |
| socks.c \ | |
| @@ -409,7 +408,6 @@ LIB_HFILES = \ | |
| setup-win32.h \ | |
| sigpipe.h \ | |
| slist.h \ | |
| - | smb.h \ |
| smtp.h \ | |
| sockaddr.h \ | |
| socketpair.h \ | |
| @@ -148,9 +148,6 @@ | |
| /* disabled shuffle DNS feature */ | |
| #cmakedefine CURL_DISABLE_SHUFFLE_DNS 1 | |
| - | /* disables SMB */ |
| - | #cmakedefine CURL_ENABLE_SMB 1 |
| - | |
| /* disables SMTP */ | |
| #cmakedefine CURL_DISABLE_SMTP 1 | |
| @@ -36,7 +36,6 @@ | |
| #include "mqtt.h" | |
| #include "pop3.h" | |
| #include "rtsp.h" | |
| - | #include "smb.h" |
| #include "smtp.h" | |
| #include "telnet.h" | |
| #include "tftp.h" | |
| @@ -308,32 +307,6 @@ const struct Curl_scheme Curl_scheme_scp = { | |
| PORT_SSH, /* defport */ | |
| }; | |
| - | const struct Curl_scheme Curl_scheme_smb = { |
| - | "smb", /* scheme */ |
| - | #if defined(CURL_ENABLE_SMB) && defined(USE_CURL_NTLM_CORE) |
| - | &Curl_protocol_smb, |
| - | #else |
| - | ZERO_NULL, |
| - | #endif |
| - | CURLPROTO_SMB, /* protocol */ |
| - | CURLPROTO_SMB, /* family */ |
| - | PROTOPT_NONE, /* flags */ |
| - | PORT_SMB, /* defport */ |
| - | }; |
| - | |
| - | const struct Curl_scheme Curl_scheme_smbs = { |
| - | "smbs", /* scheme */ |
| - | #if defined(CURL_ENABLE_SMB) && defined(USE_CURL_NTLM_CORE) && defined(USE_SSL) |
| - | &Curl_protocol_smb, |
| - | #else |
| - | ZERO_NULL, |
| - | #endif |
| - | CURLPROTO_SMBS, /* protocol */ |
| - | CURLPROTO_SMB, /* family */ |
| - | PROTOPT_SSL, /* flags */ |
| - | PORT_SMBS, /* defport */ |
| - | }; |
| - | |
| const struct Curl_scheme Curl_scheme_smtp = { | |
| "smtp", /* scheme */ | |
| #ifdef CURL_DISABLE_SMTP | |
| @@ -486,8 +459,6 @@ static const struct Curl_scheme *three_letter_scheme(const char *scheme) | |
| else if(s0 == 's') { | |
| if(s1 == 'c' && s2 == 'p') | |
| return &Curl_scheme_scp; | |
| - | if(s1 == 'm' && s2 == 'b') |
| - | return &Curl_scheme_smb; |
| } | |
| return NULL; | |
| } | |
| @@ -544,10 +515,6 @@ static const struct Curl_scheme *four_letter_scheme(const char *scheme) | |
| if(s1 == 'i' && s2 == 'c' && s3 == 't') | |
| return &Curl_scheme_dict; | |
| } | |
| - | else if(s0 == 's') { |
| - | if(s1 == 'm' && s2 == 'b' && s3 == 's') |
| - | return &Curl_scheme_smbs; |
| - | } |
| return NULL; | |
| } | |
| @@ -45,8 +45,6 @@ struct easy_pollset; | |
| #define PORT_IMAPS 993 | |
| #define PORT_POP3 110 | |
| #define PORT_POP3S 995 | |
| - | #define PORT_SMB 445 |
| - | #define PORT_SMBS 445 |
| #define PORT_SMTP 25 | |
| #define PORT_SMTPS 465 /* sometimes called SSMTP */ | |
| #define PORT_RTSP 554 | |
| @@ -85,7 +83,6 @@ typedef curl_off_t curl_prot_t; | |
| CURLPROTO_WSS) | |
| #define PROTO_FAMILY_FTP (CURLPROTO_FTP | CURLPROTO_FTPS) | |
| #define PROTO_FAMILY_POP3 (CURLPROTO_POP3 | CURLPROTO_POP3S) | |
| - | #define PROTO_FAMILY_SMB (CURLPROTO_SMB | CURLPROTO_SMBS) |
| #define PROTO_FAMILY_SMTP (CURLPROTO_SMTP | CURLPROTO_SMTPS) | |
| #define PROTO_FAMILY_SSH (CURLPROTO_SCP | CURLPROTO_SFTP) | |
| @@ -278,8 +275,6 @@ extern const struct Curl_scheme Curl_scheme_pop3s; | |
| extern const struct Curl_scheme Curl_scheme_rtsp; | |
| extern const struct Curl_scheme Curl_scheme_scp; | |
| extern const struct Curl_scheme Curl_scheme_sftp; | |
| - | extern const struct Curl_scheme Curl_scheme_smb; |
| - | extern const struct Curl_scheme Curl_scheme_smbs; |
| extern const struct Curl_scheme Curl_scheme_smtp; | |
| extern const struct Curl_scheme Curl_scheme_smtps; | |
| extern const struct Curl_scheme Curl_scheme_socks; | |
| @@ -1,1243 +0,0 @@ | |
| - | /*************************************************************************** |
| - | * _ _ ____ _ |
| - | * Project ___| | | | _ \| | |
| - | * / __| | | | |_) | | |
| - | * | (__| |_| | _ <| |___ |
| - | * \___|\___/|_| \_\_____| |
| - | * |
| - | * Copyright (C) Daniel Stenberg, <[email protected]>, et al. |
| - | * Copyright (C) Bill Nagel <[email protected]>, Exacq Technologies |
| - | * |
| - | * This software is licensed as described in the file COPYING, which |
| - | * you should have received as part of this distribution. The terms |
| - | * are also available at https://curl.se/docs/copyright.html. |
| - | * |
| - | * You may opt to use, copy, modify, merge, publish, distribute and/or sell |
| - | * copies of the Software, and permit persons to whom the Software is |
| - | * furnished to do so, under the terms of the COPYING file. |
| - | * |
| - | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| - | * KIND, either express or implied. |
| - | * |
| - | * SPDX-License-Identifier: curl |
| - | * |
| - | ***************************************************************************/ |
| - | #include "curl_setup.h" |
| - | #include "urldata.h" |
| - | |
| - | #if defined(CURL_ENABLE_SMB) && defined(USE_CURL_NTLM_CORE) |
| - | |
| - | #ifdef HAVE_ARPA_INET_H |
| - | #include <arpa/inet.h> /* for htons() */ |
| - | #endif |
| - | |
| - | #include "smb.h" |
| - | #include "url.h" |
| - | #include "sendf.h" |
| - | #include "curl_trc.h" |
| - | #include "cfilters.h" |
| - | #include "connect.h" |
| - | #include "progress.h" |
| - | #include "transfer.h" |
| - | #include "select.h" |
| - | #include "curl_ntlm_core.h" |
| - | #include "escape.h" |
| - | #include "curl_endian.h" |
| - | #include "curlx/strcopy.h" |
| - | |
| - | /* meta key for storing protocol meta at easy handle */ |
| - | #define CURL_META_SMB_EASY "meta:proto:smb:easy" |
| - | /* meta key for storing protocol meta at connection */ |
| - | #define CURL_META_SMB_CONN "meta:proto:smb:conn" |
| - | |
| - | enum smb_conn_state { |
| - | SMB_NOT_CONNECTED = 0, |
| - | SMB_CONNECTING, |
| - | SMB_NEGOTIATE, |
| - | SMB_SETUP, |
| - | SMB_CONNECTED |
| - | }; |
| - | |
| - | /* SMB connection data, kept at connection */ |
| - | struct smb_conn { |
| - | enum smb_conn_state state; |
| - | const char *user; |
| - | char *domain; |
| - | char *share; |
| - | unsigned char challenge[8]; |
| - | unsigned int session_key; |
| - | unsigned short uid; |
| - | char *recv_buf; |
| - | char *send_buf; |
| - | size_t upload_size; |
| - | size_t send_size; |
| - | size_t sent; |
| - | size_t got; |
| - | }; |
| - | |
| - | /* SMB request state */ |
| - | enum smb_req_state { |
| - | SMB_REQUESTING, |
| - | SMB_TREE_CONNECT, |
| - | SMB_OPEN, |
| - | SMB_DOWNLOAD, |
| - | SMB_UPLOAD, |
| - | SMB_CLOSE, |
| - | SMB_TREE_DISCONNECT, |
| - | SMB_DONE |
| - | }; |
| - | |
| - | /* SMB request data, kept at easy handle */ |
| - | struct smb_request { |
| - | enum smb_req_state state; |
| - | char *path; |
| - | unsigned short tid; /* Even if we connect to the same tree as another */ |
| - | unsigned short fid; /* request, the tid will be different */ |
| - | CURLcode result; |
| - | }; |
| - | |
| - | /* |
| - | * Definitions for SMB protocol data structures |
| - | */ |
| - | #if defined(_MSC_VER) || defined(__ILEC400__) |
| - | # define PACK |
| - | # pragma pack(push) |
| - | # pragma pack(1) |
| - | #elif defined(__GNUC__) |
| - | # define PACK __attribute__((packed)) |
| - | #else |
| - | # define PACK |
| - | #endif |
| - | |
| - | #define SMB_COM_CLOSE 0x04 |
| - | #define SMB_COM_READ_ANDX 0x2e |
| - | #define SMB_COM_WRITE_ANDX 0x2f |
| - | #define SMB_COM_TREE_DISCONNECT 0x71 |
| - | #define SMB_COM_NEGOTIATE 0x72 |
| - | #define SMB_COM_SETUP_ANDX 0x73 |
| - | #define SMB_COM_TREE_CONNECT_ANDX 0x75 |
| - | #define SMB_COM_NT_CREATE_ANDX 0xa2 |
| - | #define SMB_COM_NO_ANDX_COMMAND 0xff |
| - | |
| - | #define SMB_WC_CLOSE 0x03 |
| - | #define SMB_WC_READ_ANDX 0x0c |
| - | #define SMB_WC_WRITE_ANDX 0x0e |
| - | #define SMB_WC_SETUP_ANDX 0x0d |
| - | #define SMB_WC_TREE_CONNECT_ANDX 0x04 |
| - | #define SMB_WC_NT_CREATE_ANDX 0x18 |
| - | |
| - | #define SMB_FLAGS_CANONICAL_PATHNAMES 0x10 |
| - | #define SMB_FLAGS_CASELESS_PATHNAMES 0x08 |
| - | /* #define SMB_FLAGS2_UNICODE_STRINGS 0x8000 */ |
| - | #define SMB_FLAGS2_IS_LONG_NAME 0x0040 |
| - | #define SMB_FLAGS2_KNOWS_LONG_NAME 0x0001 |
| - | |
| - | #define SMB_CAP_LARGE_FILES 0x08 |
| - | #define SMB_GENERIC_WRITE 0x40000000 |
| - | #define SMB_GENERIC_READ 0x80000000 |
| - | #define SMB_FILE_SHARE_ALL 0x07 |
| - | #define SMB_FILE_OPEN 0x01 |
| - | #define SMB_FILE_OVERWRITE_IF 0x05 |
| - | |
| - | #define SMB_ERR_NOACCESS 0x00050001 |
| - | |
| - | struct smb_header { |
| - | unsigned char nbt_type; |
| - | unsigned char nbt_flags; |
| - | unsigned short nbt_length; |
| - | unsigned char magic[4]; |
| - | unsigned char command; |
| - | unsigned int status; |
| - | unsigned char flags; |
| - | unsigned short flags2; |
| - | unsigned short pid_high; |
| - | unsigned char signature[8]; |
| - | unsigned short pad; |
| - | unsigned short tid; |
| - | unsigned short pid; |
| - | unsigned short uid; |
| - | unsigned short mid; |
| - | } PACK; |
| - | |
| - | struct smb_negotiate_response { |
| - | struct smb_header h; |
| - | unsigned char word_count; |
| - | unsigned short dialect_index; |
| - | unsigned char security_mode; |
| - | unsigned short max_mpx_count; |
| - | unsigned short max_number_vcs; |
| - | unsigned int max_buffer_size; |
| - | unsigned int max_raw_size; |
| - | unsigned int session_key; |
| - | unsigned int capabilities; |
| - | unsigned int system_time_low; |
| - | unsigned int system_time_high; |
| - | unsigned short server_time_zone; |
| - | unsigned char encryption_key_length; |
| - | unsigned short byte_count; |
| - | char bytes[1]; |
| - | } PACK; |
| - | |
| - | struct andx { |
| - | unsigned char command; |
| - | unsigned char pad; |
| - | unsigned short offset; |
| - | } PACK; |
| - | |
| - | struct smb_setup { |
| - | unsigned char word_count; |
| - | struct andx andx; |
| - | unsigned short max_buffer_size; |
| - | unsigned short max_mpx_count; |
| - | unsigned short vc_number; |
| - | unsigned int session_key; |
| - | unsigned short lengths[2]; |
| - | unsigned int pad; |
| - | unsigned int capabilities; |
| - | unsigned short byte_count; |
| - | char bytes[1024]; |
| - | } PACK; |
| - | |
| - | struct smb_tree_connect { |
| - | unsigned char word_count; |
| - | struct andx andx; |
| - | unsigned short flags; |
| - | unsigned short pw_len; |
| - | unsigned short byte_count; |
| - | char bytes[1024]; |
| - | } PACK; |
| - | |
| - | struct smb_nt_create { |
| - | unsigned char word_count; |
| - | struct andx andx; |
| - | unsigned char pad; |
| - | unsigned short name_length; |
| - | unsigned int flags; |
| - | unsigned int root_fid; |
| - | unsigned int access; |
| - | curl_off_t allocation_size; |
| - | unsigned int ext_file_attributes; |
| - | unsigned int share_access; |
| - | unsigned int create_disposition; |
| - | unsigned int create_options; |
| - | unsigned int impersonation_level; |
| - | unsigned char security_flags; |
| - | unsigned short byte_count; |
| - | char bytes[1024]; |
| - | } PACK; |
| - | |
| - | struct smb_nt_create_response { |
| - | struct smb_header h; |
| - | unsigned char word_count; |
| - | struct andx andx; |
| - | unsigned char op_lock_level; |
| - | unsigned short fid; |
| - | unsigned int create_disposition; |
| - | |
| - | curl_off_t create_time; |
| - | curl_off_t last_access_time; |
| - | curl_off_t last_write_time; |
| - | curl_off_t last_change_time; |
| - | unsigned int ext_file_attributes; |
| - | curl_off_t allocation_size; |
| - | curl_off_t end_of_file; |
| - | } PACK; |
| - | |
| - | struct smb_read { |
| - | unsigned char word_count; |
| - | struct andx andx; |
| - | unsigned short fid; |
| - | unsigned int offset; |
| - | unsigned short max_bytes; |
| - | unsigned short min_bytes; |
| - | unsigned int timeout; |
| - | unsigned short remaining; |
| - | unsigned int offset_high; |
| - | unsigned short byte_count; |
| - | } PACK; |
| - | |
| - | struct smb_write { |
| - | struct smb_header h; |
| - | unsigned char word_count; |
| - | struct andx andx; |
| - | unsigned short fid; |
| - | unsigned int offset; |
| - | unsigned int timeout; |
| - | unsigned short write_mode; |
| - | unsigned short remaining; |
| - | unsigned short pad; |
| - | unsigned short data_length; |
| - | unsigned short data_offset; |
| - | unsigned int offset_high; |
| - | unsigned short byte_count; |
| - | unsigned char pad2; |
| - | } PACK; |
| - | |
| - | struct smb_close { |
| - | unsigned char word_count; |
| - | unsigned short fid; |
| - | unsigned int last_mtime; |
| - | unsigned short byte_count; |
| - | } PACK; |
| - | |
| - | struct smb_tree_disconnect { |
| - | unsigned char word_count; |
| - | unsigned short byte_count; |
| - | } PACK; |
| - | |
| - | #if defined(_MSC_VER) || defined(__ILEC400__) |
| - | # pragma pack(pop) |
| - | #endif |
| - | |
| - | #define MAX_PAYLOAD_SIZE 0x8000 |
| - | #define MAX_MESSAGE_SIZE (MAX_PAYLOAD_SIZE + 0x1000) |
| - | #define CLIENTNAME "curl" |
| - | #define SERVICENAME "?????" |
| - | |
| - | /* SMB is mostly little endian */ |
| - | #if (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || \ |
| - | defined(__OS400__) |
| - | static unsigned short smb_swap16(unsigned short x) |
| - | { |
| - | return (unsigned short)((x << 8) | ((x >> 8) & 0xff)); |
| - | } |
| - | |
| - | static unsigned int smb_swap32(unsigned int x) |
| - | { |
| - | return (x << 24) | ((x << 8) & 0xff0000) | ((x >> 8) & 0xff00) | |
| - | ((x >> 24) & 0xff); |
| - | } |
| - | |
| - | static curl_off_t smb_swap64(curl_off_t x) |
| - | { |
| - | return ((curl_off_t)smb_swap32((unsigned int)x) << 32) | |
| - | smb_swap32((unsigned int)(x >> 32)); |
| - | } |
| - | |
| - | #else |
| - | # define smb_swap16(x) (x) |
| - | # define smb_swap32(x) (x) |
| - | # define smb_swap64(x) (x) |
| - | #endif |
| - | |
| - | static void conn_state(struct Curl_easy *data, struct smb_conn *smbc, |
| - | enum smb_conn_state newstate) |
| - | { |
| - | #if defined(DEBUGBUILD) && defined(CURLVERBOSE) |
| - | /* For debug purposes */ |
| - | static const char * const names[] = { |
| - | "SMB_NOT_CONNECTED", |
| - | "SMB_CONNECTING", |
| - | "SMB_NEGOTIATE", |
| - | "SMB_SETUP", |
| - | "SMB_CONNECTED", |
| - | /* LAST */ |
| - | }; |
| - | |
| - | if(smbc->state != newstate) |
| - | infof(data, "SMB conn %p state change from %s to %s", |
| - | (void *)smbc, names[smbc->state], names[newstate]); |
| - | #else |
| - | (void)data; |
| - | #endif |
| - | smbc->state = newstate; |
| - | } |
| - | |
| - | static void request_state(struct Curl_easy *data, |
| - | enum smb_req_state newstate) |
| - | { |
| - | struct smb_request *req = Curl_meta_get(data, CURL_META_SMB_EASY); |
| - | if(req) { |
| - | #if defined(DEBUGBUILD) && defined(CURLVERBOSE) |
| - | /* For debug purposes */ |
| - | static const char * const names[] = { |
| - | "SMB_REQUESTING", |
| - | "SMB_TREE_CONNECT", |
| - | "SMB_OPEN", |
| - | "SMB_DOWNLOAD", |
| - | "SMB_UPLOAD", |
| - | "SMB_CLOSE", |
| - | "SMB_TREE_DISCONNECT", |
| - | "SMB_DONE", |
| - | /* LAST */ |
| - | }; |
| - | |
| - | if(req->state != newstate) |
| - | infof(data, "SMB request %p state change from %s to %s", |
| - | (void *)req, names[req->state], names[newstate]); |
| - | #endif |
| - | |
| - | req->state = newstate; |
| - | } |
| - | } |
| - | |
| - | static void smb_easy_dtor(const void *key, size_t klen, void *entry) |
| - | { |
| - | struct smb_request *req = entry; |
| - | (void)key; |
| - | (void)klen; |
| - | curlx_safefree(req->path); |
| - | curlx_free(req); |
| - | } |
| - | |
| - | static void smb_conn_dtor(const void *key, size_t klen, void *entry) |
| - | { |
| - | struct smb_conn *smbc = entry; |
| - | (void)key; |
| - | (void)klen; |
| - | curlx_safefree(smbc->share); |
| - | curlx_safefree(smbc->domain); |
| - | curlx_safefree(smbc->recv_buf); |
| - | curlx_safefree(smbc->send_buf); |
| - | curlx_free(smbc); |
| - | } |
| - | |
| - | static CURLcode smb_parse_url_path(struct Curl_easy *data, |
| - | struct smb_conn *smbc, |
| - | struct smb_request *req) |
| - | { |
| - | char *path; |
| - | char *slash, *s; |
| - | CURLcode result; |
| - | |
| - | /* URL decode the path */ |
| - | result = Curl_urldecode(data->state.up.path, 0, &path, NULL, REJECT_CTRL); |
| - | if(result) |
| - | return result; |
| - | |
| - | /* Parse the path for the share */ |
| - | curlx_safefree(smbc->share); |
| - | smbc->share = curlx_strdup((*path == '/' || *path == '\\') |
| - | ? path + 1 : path); |
| - | curlx_free(path); |
| - | if(!smbc->share) |
| - | return CURLE_OUT_OF_MEMORY; |
| - | |
| - | slash = strchr(smbc->share, '/'); |
| - | if(!slash) |
| - | slash = strchr(smbc->share, '\\'); |
| - | |
| - | /* The share must be present */ |
| - | if(!slash) { |
| - | curlx_safefree(smbc->share); |
| - | failf(data, "missing share in URL path for SMB"); |
| - | return CURLE_URL_MALFORMAT; |
| - | } |
| - | |
| - | /* Parse the path for the file path converting any forward slashes into |
| - | backslashes */ |
| - | *slash++ = 0; |
| - | for(s = slash; *s; s++) { |
| - | if(*s == '/') |
| - | *s = '\\'; |
| - | } |
| - | /* keep a copy at easy struct to not share this with connection state */ |
| - | req->path = curlx_strdup(slash); |
| - | if(!req->path) |
| - | return CURLE_OUT_OF_MEMORY; |
| - | |
| - | return CURLE_OK; |
| - | } |
| - | |
| - | /* this should setup things in the connection, not in the easy |
| - | handle */ |
| - | static CURLcode smb_setup_connection(struct Curl_easy *data, |
| - | struct connectdata *conn) |
| - | { |
| - | struct smb_conn *smbc; |
| - | struct smb_request *req; |
| - | |
| - | /* Initialize the connection state */ |
| - | smbc = curlx_calloc(1, sizeof(*smbc)); |
| - | if(!smbc || |
| - | Curl_conn_meta_set(conn, CURL_META_SMB_CONN, smbc, smb_conn_dtor)) |
| - | return CURLE_OUT_OF_MEMORY; |
| - | |
| - | /* Initialize the request state */ |
| - | req = curlx_calloc(1, sizeof(*req)); |
| - | if(!req || |
| - | Curl_meta_set(data, CURL_META_SMB_EASY, req, smb_easy_dtor)) |
| - | return CURLE_OUT_OF_MEMORY; |
| - | |
| - | /* Parse the URL path */ |
| - | return smb_parse_url_path(data, smbc, req); |
| - | } |
| - | |
| - | static CURLcode smb_connect(struct Curl_easy *data, bool *done) |
| - | { |
| - | struct connectdata *conn = data->conn; |
| - | struct smb_conn *smbc = Curl_conn_meta_get(conn, CURL_META_SMB_CONN); |
| - | const char *slash; |
| - | const char *user = Curl_creds_user(conn->creds); |
| - | |
| - | (void)done; |
| - | if(!smbc) |
| - | return CURLE_FAILED_INIT; |
| - | |
| - | /* Check we have a username and password to authenticate with */ |
| - | if(!Curl_creds_has_user(data->state.creds)) |
| - | return CURLE_LOGIN_DENIED; |
| - | |
| - | /* Initialize the connection state */ |
| - | smbc->state = SMB_CONNECTING; |
| - | smbc->recv_buf = curlx_malloc(MAX_MESSAGE_SIZE); |
| - | if(!smbc->recv_buf) |
| - | return CURLE_OUT_OF_MEMORY; |
| - | smbc->send_buf = curlx_malloc(MAX_MESSAGE_SIZE); |
| - | if(!smbc->send_buf) |
| - | return CURLE_OUT_OF_MEMORY; |
| - | |
| - | /* Parse the username, domain, and password */ |
| - | slash = strchr(user, '/'); |
| - | if(!slash) |
| - | slash = strchr(user, '\\'); |
| - | |
| - | if(slash) { |
| - | smbc->user = slash + 1; |
| - | smbc->domain = curlx_strdup(user); |
| - | if(!smbc->domain) |
| - | return CURLE_OUT_OF_MEMORY; |
| - | smbc->domain[slash - user] = 0; |
| - | } |
| - | else { |
| - | smbc->user = user; |
| - | smbc->domain = curlx_strdup(conn->origin->hostname); |
| - | if(!smbc->domain) |
| - | return CURLE_OUT_OF_MEMORY; |
| - | } |
| - | |
| - | return CURLE_OK; |
| - | } |
| - | |
| - | static CURLcode smb_recv_message(struct Curl_easy *data, |
| - | struct smb_conn *smbc, |
| - | void **msg) |
| - | { |
| - | char *buf = smbc->recv_buf; |
| - | size_t bytes_read; |
| - | size_t nbt_size; |
| - | size_t msg_size = sizeof(struct smb_header); |
| - | size_t len = MAX_MESSAGE_SIZE - smbc->got; |
| - | CURLcode result; |
| - | |
| - | result = Curl_xfer_recv(data, buf + smbc->got, len, &bytes_read); |
| - | if(result) |
| - | return result; |
| - | |
| - | if(!bytes_read) |
| - | return CURLE_OK; |
| - | |
| - | smbc->got += bytes_read; |
| - | |
| - | /* Check for a 32-bit nbt header */ |
| - | if(smbc->got < sizeof(unsigned int)) |
| - | return CURLE_OK; |
| - | |
| - | nbt_size = Curl_read16_be((const unsigned char *) |
| - | (buf + sizeof(unsigned short))) + |
| - | sizeof(unsigned int); |
| - | if(nbt_size > MAX_MESSAGE_SIZE) { |
| - | failf(data, "too large NetBIOS frame size %zu", nbt_size); |
| - | return CURLE_RECV_ERROR; |
| - | } |
| - | else if(nbt_size < msg_size) { |
| - | /* Each SMB message must be at least this large, e.g. 32 bytes */ |
| - | failf(data, "too small NetBIOS frame size %zu", nbt_size); |
| - | return CURLE_RECV_ERROR; |
| - | } |
| - | |
| - | if(smbc->got < nbt_size) |
| - | return CURLE_OK; |
| - | |
| - | if(nbt_size >= msg_size + 1) { |
| - | /* Add the word count */ |
| - | msg_size += 1 + (((unsigned char)buf[msg_size]) * sizeof(unsigned short)); |
| - | if(nbt_size >= msg_size + sizeof(unsigned short)) { |
| - | /* Add the byte count */ |
| - | msg_size += sizeof(unsigned short) + |
| - | Curl_read16_le((const unsigned char *)&buf[msg_size]); |
| - | if(nbt_size < msg_size) |
| - | return CURLE_RECV_ERROR; |
| - | } |
| - | } |
| - | |
| - | *msg = buf; |
| - | |
| - | return CURLE_OK; |
| - | } |
| - | |
| - | static void smb_pop_message(struct smb_conn *smbc) |
| - | { |
| - | smbc->got = 0; |
| - | } |
| - | |
| - | static void smb_format_message(struct smb_conn *smbc, |
| - | struct smb_request *req, |
| - | struct smb_header *h, |
| - | unsigned char cmd, size_t len) |
| - | { |
| - | const unsigned int pid = 0xbad71d; /* made up */ |
| - | |
| - | memset(h, 0, sizeof(*h)); |
| - | h->nbt_length = htons((unsigned short)(sizeof(*h) - sizeof(unsigned int) + |
| - | len)); |
| - | memcpy((char *)h->magic, "\xffSMB", 4); |
| - | h->command = cmd; |
| - | h->flags = SMB_FLAGS_CANONICAL_PATHNAMES | SMB_FLAGS_CASELESS_PATHNAMES; |
| - | h->flags2 = smb_swap16(SMB_FLAGS2_IS_LONG_NAME | SMB_FLAGS2_KNOWS_LONG_NAME); |
| - | h->uid = smb_swap16(smbc->uid); |
| - | h->tid = smb_swap16(req->tid); |
| - | h->pid_high = smb_swap16((unsigned short)(pid >> 16)); |
| - | h->pid = smb_swap16((unsigned short)pid); |
| - | } |
| - | |
| - | static CURLcode smb_send(struct Curl_easy *data, struct smb_conn *smbc, |
| - | size_t len, size_t upload_size) |
| - | { |
| - | size_t bytes_written; |
| - | CURLcode result; |
| - | |
| - | result = Curl_xfer_send(data, smbc->send_buf, len, FALSE, &bytes_written); |
| - | if(result) |
| - | return result; |
| - | |
| - | if(bytes_written != len) { |
| - | smbc->send_size = len; |
| - | smbc->sent = bytes_written; |
| - | } |
| - | |
| - | smbc->upload_size = upload_size; |
| - | |
| - | return CURLE_OK; |
| - | } |
| - | |
| - | static CURLcode smb_flush(struct Curl_easy *data, struct smb_conn *smbc) |
| - | { |
| - | size_t bytes_written; |
| - | size_t len = smbc->send_size - smbc->sent; |
| - | CURLcode result; |
| - | |
| - | if(!smbc->send_size) |
| - | return CURLE_OK; |
| - | |
| - | result = Curl_xfer_send(data, smbc->send_buf + smbc->sent, len, FALSE, |
| - | &bytes_written); |
| - | if(result) |
| - | return result; |
| - | |
| - | if(bytes_written != len) |
| - | smbc->sent += bytes_written; |
| - | else |
| - | smbc->send_size = 0; |
| - | |
| - | return CURLE_OK; |
| - | } |
| - | |
| - | static CURLcode smb_send_message(struct Curl_easy *data, |
| - | struct smb_conn *smbc, |
| - | struct smb_request *req, |
| - | unsigned char cmd, |
| - | const void *msg, size_t msg_len) |
| - | { |
| - | if((MAX_MESSAGE_SIZE - sizeof(struct smb_header)) < msg_len) { |
| - | DEBUGASSERT(0); |
| - | return CURLE_SEND_ERROR; |
| - | } |
| - | smb_format_message(smbc, req, (struct smb_header *)smbc->send_buf, |
| - | cmd, msg_len); |
| - | memcpy(smbc->send_buf + sizeof(struct smb_header), msg, msg_len); |
| - | |
| - | return smb_send(data, smbc, sizeof(struct smb_header) + msg_len, 0); |
| - | } |
| - | |
| - | static CURLcode smb_send_negotiate(struct Curl_easy *data, |
| - | struct smb_conn *smbc, |
| - | struct smb_request *req) |
| - | { |
| - | static const char msg[] = "\x00\x0c\x00\x02NT LM 0.12"; |
| - | |
| - | return smb_send_message(data, smbc, req, SMB_COM_NEGOTIATE, msg, |
| - | sizeof(msg)); |
| - | } |
| - | |
| - | static CURLcode smb_send_setup(struct Curl_easy *data) |
| - | { |
| - | struct connectdata *conn = data->conn; |
| - | struct smb_conn *smbc = Curl_conn_meta_get(conn, CURL_META_SMB_CONN); |
| - | struct smb_request *req = Curl_meta_get(data, CURL_META_SMB_EASY); |
| - | struct smb_setup msg; |
| - | char *p = msg.bytes; |
| - | unsigned char lm_hash[21]; |
| - | unsigned char lm[24]; |
| - | unsigned char nt_hash[21]; |
| - | unsigned char nt[24]; |
| - | size_t byte_count; |
| - | const char *passwd = Curl_creds_passwd(conn->creds); |
| - | |
| - | if(!smbc || !req) |
| - | return CURLE_FAILED_INIT; |
| - | |
| - | byte_count = sizeof(lm) + sizeof(nt) + |
| - | strlen(smbc->user) + strlen(smbc->domain) + |
| - | CURL_CSTRLEN(CURL_OS) + CURL_CSTRLEN(CLIENTNAME) + 4; /* 4 null chars */ |
| - | if(byte_count > sizeof(msg.bytes)) |
| - | return CURLE_FILESIZE_EXCEEDED; |
| - | |
| - | Curl_ntlm_core_mk_lm_hash(passwd, lm_hash); |
| - | Curl_ntlm_core_lm_resp(lm_hash, smbc->challenge, lm); |
| - | Curl_ntlm_core_mk_nt_hash(passwd, nt_hash); |
| - | Curl_ntlm_core_lm_resp(nt_hash, smbc->challenge, nt); |
| - | |
| - | memset(&msg, 0, sizeof(msg) - sizeof(msg.bytes)); |
| - | msg.word_count = SMB_WC_SETUP_ANDX; |
| - | msg.andx.command = SMB_COM_NO_ANDX_COMMAND; |
| - | msg.max_buffer_size = smb_swap16(MAX_MESSAGE_SIZE); |
| - | msg.max_mpx_count = smb_swap16(1); |
| - | msg.vc_number = smb_swap16(1); |
| - | msg.session_key = smb_swap32(smbc->session_key); |
| - | msg.capabilities = smb_swap32(SMB_CAP_LARGE_FILES); |
| - | msg.lengths[0] = smb_swap16(sizeof(lm)); |
| - | msg.lengths[1] = smb_swap16(sizeof(nt)); |
| - | memcpy(p, lm, sizeof(lm)); |
| - | p += sizeof(lm); |
| - | memcpy(p, nt, sizeof(nt)); |
| - | p += sizeof(nt); |
| - | p += curl_msnprintf(p, byte_count - sizeof(nt) - sizeof(lm), |
| - | "%s%c" /* user */ |
| - | "%s%c" /* domain */ |
| - | "%s%c" /* OS */ |
| - | "%s", /* client name */ |
| - | smbc->user, 0, smbc->domain, 0, CURL_OS, 0, CLIENTNAME); |
| - | p++; /* count the final null-termination */ |
| - | DEBUGASSERT(byte_count == (size_t)(p - msg.bytes)); |
| - | msg.byte_count = smb_swap16((unsigned short)byte_count); |
| - | |
| - | return smb_send_message(data, smbc, req, SMB_COM_SETUP_ANDX, &msg, |
| - | sizeof(msg) - sizeof(msg.bytes) + byte_count); |
| - | } |
| - | |
| - | static CURLcode smb_send_tree_connect(struct Curl_easy *data, |
| - | struct smb_conn *smbc, |
| - | struct smb_request *req) |
| - | { |
| - | struct smb_tree_connect msg; |
| - | struct connectdata *conn = data->conn; |
| - | char *p = msg.bytes; |
| - | const size_t byte_count = strlen(conn->origin->hostname) + |
| - | strlen(smbc->share) + |
| - | CURL_CSTRLEN(SERVICENAME) + 5; /* 2 nulls and 3 backslashes */ |
| - | |
| - | if(byte_count > sizeof(msg.bytes)) |
| - | return CURLE_FILESIZE_EXCEEDED; |
| - | |
| - | memset(&msg, 0, sizeof(msg) - sizeof(msg.bytes)); |
| - | msg.word_count = SMB_WC_TREE_CONNECT_ANDX; |
| - | msg.andx.command = SMB_COM_NO_ANDX_COMMAND; |
| - | msg.pw_len = 0; |
| - | |
| - | p += curl_msnprintf(p, byte_count, |
| - | "\\\\%s\\" /* hostname */ |
| - | "%s%c" /* share */ |
| - | "%s", /* service */ |
| - | conn->origin->hostname, smbc->share, 0, SERVICENAME); |
| - | p++; /* count the final null-termination */ |
| - | DEBUGASSERT(byte_count == (size_t)(p - msg.bytes)); |
| - | msg.byte_count = smb_swap16((unsigned short)byte_count); |
| - | |
| - | return smb_send_message(data, smbc, req, SMB_COM_TREE_CONNECT_ANDX, &msg, |
| - | sizeof(msg) - sizeof(msg.bytes) + byte_count); |
| - | } |
| - | |
| - | static CURLcode smb_send_open(struct Curl_easy *data, |
| - | struct smb_conn *smbc, |
| - | struct smb_request *req) |
| - | { |
| - | struct smb_nt_create msg; |
| - | const size_t byte_count = strlen(req->path) + 1; |
| - | |
| - | if(byte_count > sizeof(msg.bytes)) |
| - | return CURLE_FILESIZE_EXCEEDED; |
| - | |
| - | memset(&msg, 0, sizeof(msg) - sizeof(msg.bytes)); |
| - | msg.word_count = SMB_WC_NT_CREATE_ANDX; |
| - | msg.andx.command = SMB_COM_NO_ANDX_COMMAND; |
| - | msg.name_length = smb_swap16((unsigned short)(byte_count - 1)); |
| - | msg.share_access = smb_swap32(SMB_FILE_SHARE_ALL); |
| - | if(data->state.upload) { |
| - | msg.access = smb_swap32(SMB_GENERIC_READ | SMB_GENERIC_WRITE); |
| - | msg.create_disposition = smb_swap32(SMB_FILE_OVERWRITE_IF); |
| - | } |
| - | else { |
| - | msg.access = smb_swap32(SMB_GENERIC_READ); |
| - | msg.create_disposition = smb_swap32(SMB_FILE_OPEN); |
| - | } |
| - | msg.byte_count = smb_swap16((unsigned short)byte_count); |
| - | curlx_strcopy(msg.bytes, sizeof(msg.bytes), req->path, byte_count - 1); |
| - | |
| - | return smb_send_message(data, smbc, req, SMB_COM_NT_CREATE_ANDX, &msg, |
| - | sizeof(msg) - sizeof(msg.bytes) + byte_count); |
| - | } |
| - | |
| - | static CURLcode smb_send_close(struct Curl_easy *data, |
| - | struct smb_conn *smbc, |
| - | struct smb_request *req) |
| - | { |
| - | struct smb_close msg; |
| - | |
| - | memset(&msg, 0, sizeof(msg)); |
| - | msg.word_count = SMB_WC_CLOSE; |
| - | msg.fid = smb_swap16(req->fid); |
| - | |
| - | return smb_send_message(data, smbc, req, SMB_COM_CLOSE, &msg, sizeof(msg)); |
| - | } |
| - | |
| - | static CURLcode smb_send_tree_disconnect(struct Curl_easy *data, |
| - | struct smb_conn *smbc, |
| - | struct smb_request *req) |
| - | { |
| - | struct smb_tree_disconnect msg; |
| - | memset(&msg, 0, sizeof(msg)); |
| - | return smb_send_message(data, smbc, req, SMB_COM_TREE_DISCONNECT, |
| - | &msg, sizeof(msg)); |
| - | } |
| - | |
| - | static CURLcode smb_send_read(struct Curl_easy *data, |
| - | struct smb_conn *smbc, |
| - | struct smb_request *req) |
| - | { |
| - | curl_off_t offset = data->req.offset; |
| - | struct smb_read msg; |
| - | |
| - | memset(&msg, 0, sizeof(msg)); |
| - | msg.word_count = SMB_WC_READ_ANDX; |
| - | msg.andx.command = SMB_COM_NO_ANDX_COMMAND; |
| - | msg.fid = smb_swap16(req->fid); |
| - | msg.offset = smb_swap32((unsigned int)offset); |
| - | msg.offset_high = smb_swap32((unsigned int)(offset >> 32)); |
| - | msg.min_bytes = smb_swap16(MAX_PAYLOAD_SIZE); |
| - | msg.max_bytes = smb_swap16(MAX_PAYLOAD_SIZE); |
| - | |
| - | return smb_send_message(data, smbc, req, SMB_COM_READ_ANDX, |
| - | &msg, sizeof(msg)); |
| - | } |
| - | |
| - | static CURLcode smb_send_write(struct Curl_easy *data, |
| - | struct smb_conn *smbc, |
| - | struct smb_request *req) |
| - | { |
| - | struct smb_write *msg; |
| - | curl_off_t offset = data->req.offset; |
| - | curl_off_t upload_size = data->req.size - data->req.bytecount; |
| - | |
| - | msg = (struct smb_write *)smbc->send_buf; |
| - | if(upload_size >= MAX_PAYLOAD_SIZE - 1) /* There is one byte of padding */ |
| - | upload_size = MAX_PAYLOAD_SIZE - 1; |
| - | |
| - | memset(msg, 0, sizeof(*msg)); |
| - | msg->word_count = SMB_WC_WRITE_ANDX; |
| - | msg->andx.command = SMB_COM_NO_ANDX_COMMAND; |
| - | msg->fid = smb_swap16(req->fid); |
| - | msg->offset = smb_swap32((unsigned int)offset); |
| - | msg->offset_high = smb_swap32((unsigned int)(offset >> 32)); |
| - | msg->data_length = smb_swap16((unsigned short)upload_size); |
| - | msg->data_offset = smb_swap16(sizeof(*msg) - sizeof(unsigned int)); |
| - | msg->byte_count = smb_swap16((unsigned short)(upload_size + 1)); |
| - | |
| - | smb_format_message(smbc, req, &msg->h, SMB_COM_WRITE_ANDX, |
| - | sizeof(*msg) - sizeof(msg->h) + (size_t)upload_size); |
| - | |
| - | return smb_send(data, smbc, sizeof(*msg), (size_t)upload_size); |
| - | } |
| - | |
| - | static CURLcode smb_send_and_recv(struct Curl_easy *data, |
| - | struct smb_conn *smbc, void **msg) |
| - | { |
| - | CURLcode result; |
| - | *msg = NULL; /* if it returns early */ |
| - | |
| - | /* Check if there is data in the transfer buffer */ |
| - | if(!smbc->send_size && smbc->upload_size) { |
| - | size_t nread = smbc->upload_size > (size_t)MAX_MESSAGE_SIZE ? |
| - | (size_t)MAX_MESSAGE_SIZE : smbc->upload_size; |
| - | bool eos; |
| - | |
| - | result = Curl_client_read(data, smbc->send_buf, nread, &nread, &eos); |
| - | if(result && result != CURLE_AGAIN) |
| - | return result; |
| - | if(!nread) |
| - | return CURLE_OK; |
| - | |
| - | smbc->upload_size -= nread; |
| - | smbc->send_size = nread; |
| - | smbc->sent = 0; |
| - | } |
| - | |
| - | /* Check if there is data to send */ |
| - | if(smbc->send_size) { |
| - | result = smb_flush(data, smbc); |
| - | if(result) |
| - | return result; |
| - | } |
| - | |
| - | /* Check if there is still data to be sent */ |
| - | if(smbc->send_size || smbc->upload_size) |
| - | return CURLE_AGAIN; |
| - | |
| - | return smb_recv_message(data, smbc, msg); |
| - | } |
| - | |
| - | static CURLcode smb_connection_state(struct Curl_easy *data, bool *done) |
| - | { |
| - | struct connectdata *conn = data->conn; |
| - | struct smb_conn *smbc = Curl_conn_meta_get(conn, CURL_META_SMB_CONN); |
| - | struct smb_request *req = Curl_meta_get(data, CURL_META_SMB_EASY); |
| - | struct smb_negotiate_response *nrsp; |
| - | struct smb_header *h; |
| - | CURLcode result; |
| - | void *msg = NULL; |
| - | |
| - | if(!smbc || !req) |
| - | return CURLE_FAILED_INIT; |
| - | |
| - | if(smbc->state == SMB_CONNECTING) { |
| - | #ifdef USE_SSL |
| - | if(Curl_conn_is_ssl(conn, FIRSTSOCKET)) { |
| - | bool ssl_done = FALSE; |
| - | result = Curl_conn_connect(data, FIRSTSOCKET, FALSE, &ssl_done); |
| - | if(result && result != CURLE_AGAIN) |
| - | return result; |
| - | if(!ssl_done) |
| - | return CURLE_OK; |
| - | } |
| - | #endif |
| - | |
| - | result = smb_send_negotiate(data, smbc, req); |
| - | if(result) { |
| - | CURL_TRC_M(data, "SMB: failed to send negotiate message"); |
| - | connclose(conn); |
| - | return result; |
| - | } |
| - | |
| - | conn_state(data, smbc, SMB_NEGOTIATE); |
| - | } |
| - | |
| - | /* Send the previous message and check for a response */ |
| - | result = smb_send_and_recv(data, smbc, &msg); |
| - | if(result && result != CURLE_AGAIN) { |
| - | CURL_TRC_M(data, "SMB: failed to communicate"); |
| - | connclose(conn); |
| - | return result; |
| - | } |
| - | |
| - | if(!msg) |
| - | return CURLE_OK; |
| - | |
| - | h = msg; |
| - | |
| - | switch(smbc->state) { |
| - | case SMB_NEGOTIATE: |
| - | if((smbc->got < sizeof(*nrsp) + sizeof(smbc->challenge) - 1) || |
| - | h->status) { |
| - | CURL_TRC_M(data, "SMB: negotiation failed"); |
| - | connclose(conn); |
| - | return CURLE_COULDNT_CONNECT; |
| - | } |
| - | nrsp = msg; |
| - | #if defined(__GNUC__) && __GNUC__ >= 13 |
| - | #pragma GCC diagnostic push |
| - | /* error: 'memcpy' offset [74, 80] from the object at '<unknown>' is out of |
| - | the bounds of referenced subobject 'bytes' with type 'char[1]' */ |
| - | #pragma GCC diagnostic ignored "-Warray-bounds" |
| - | #endif |
| - | memcpy(smbc->challenge, nrsp->bytes, sizeof(smbc->challenge)); |
| - | #if defined(__GNUC__) && __GNUC__ >= 13 |
| - | #pragma GCC diagnostic pop |
| - | #endif |
| - | smbc->session_key = smb_swap32(nrsp->session_key); |
| - | result = smb_send_setup(data); |
| - | if(result) { |
| - | CURL_TRC_M(data, "SMB: failed to send setup message"); |
| - | connclose(conn); |
| - | return result; |
| - | } |
| - | conn_state(data, smbc, SMB_SETUP); |
| - | break; |
| - | |
| - | case SMB_SETUP: |
| - | if(h->status) { |
| - | CURL_TRC_M(data, "SMB: authentication failed"); |
| - | connclose(conn); |
| - | return CURLE_LOGIN_DENIED; |
| - | } |
| - | smbc->uid = smb_swap16(h->uid); |
| - | conn_state(data, smbc, SMB_CONNECTED); |
| - | *done = TRUE; |
| - | break; |
| - | |
| - | default: |
| - | smb_pop_message(smbc); |
| - | return CURLE_OK; /* ignore */ |
| - | } |
| - | |
| - | smb_pop_message(smbc); |
| - | |
| - | return CURLE_OK; |
| - | } |
| - | |
| - | /* |
| - | * Convert a timestamp from the Windows world (100 nsec units from 1 Jan 1601) |
| - | * to POSIX time. Cap the output to fit within a time_t. |
| - | */ |
| - | static void get_posix_time(time_t *out, curl_off_t timestamp) |
| - | { |
| - | if(timestamp >= (curl_off_t)116444736000000000) { |
| - | timestamp -= (curl_off_t)116444736000000000; |
| - | timestamp /= 10000000; |
| - | #if SIZEOF_TIME_T < SIZEOF_CURL_OFF_T |
| - | if(timestamp > TIME_T_MAX) |
| - | *out = TIME_T_MAX; |
| - | else if(timestamp < TIME_T_MIN) |
| - | *out = TIME_T_MIN; |
| - | else |
| - | #endif |
| - | *out = (time_t)timestamp; |
| - | } |
| - | else |
| - | *out = 0; |
| - | } |
| - | |
| - | static CURLcode smb_request_state(struct Curl_easy *data, bool *done) |
| - | { |
| - | struct connectdata *conn = data->conn; |
| - | struct smb_conn *smbc = Curl_conn_meta_get(conn, CURL_META_SMB_CONN); |
| - | struct smb_request *req = Curl_meta_get(data, CURL_META_SMB_EASY); |
| - | struct smb_header *h; |
| - | enum smb_req_state next_state = SMB_DONE; |
| - | size_t len; |
| - | size_t off; |
| - | CURLcode result; |
| - | void *msg = NULL; |
| - | const struct smb_nt_create_response *smb_m; |
| - | |
| - | if(!smbc || !req) |
| - | return CURLE_FAILED_INIT; |
| - | |
| - | if(data->state.upload && (data->state.infilesize < 0)) { |
| - | failf(data, "SMB upload needs to know the size up front"); |
| - | return CURLE_SEND_ERROR; |
| - | } |
| - | |
| - | /* Start the request */ |
| - | if(req->state == SMB_REQUESTING) { |
| - | result = smb_send_tree_connect(data, smbc, req); |
| - | if(result) { |
| - | CURL_TRC_M(data, "SMB: failed to send tree connect message"); |
| - | connclose(conn); |
| - | return result; |
| - | } |
| - | |
| - | request_state(data, SMB_TREE_CONNECT); |
| - | } |
| - | |
| - | /* Send the previous message and check for a response */ |
| - | result = smb_send_and_recv(data, smbc, &msg); |
| - | if(result && result != CURLE_AGAIN) { |
| - | CURL_TRC_M(data, "SMB: failed to communicate"); |
| - | connclose(conn); |
| - | return result; |
| - | } |
| - | |
| - | if(!msg) |
| - | return CURLE_OK; |
| - | |
| - | h = msg; |
| - | |
| - | switch(req->state) { |
| - | case SMB_TREE_CONNECT: |
| - | if(h->status) { |
| - | req->result = CURLE_REMOTE_FILE_NOT_FOUND; |
| - | if(h->status == smb_swap32(SMB_ERR_NOACCESS)) |
| - | req->result = CURLE_REMOTE_ACCESS_DENIED; |
| - | break; |
| - | } |
| - | req->tid = smb_swap16(h->tid); |
| - | next_state = SMB_OPEN; |
| - | break; |
| - | |
| - | case SMB_OPEN: |
| - | if(h->status || smbc->got < sizeof(struct smb_nt_create_response)) { |
| - | req->result = CURLE_REMOTE_FILE_NOT_FOUND; |
| - | if(h->status == smb_swap32(SMB_ERR_NOACCESS)) |
| - | req->result = CURLE_REMOTE_ACCESS_DENIED; |
| - | next_state = SMB_TREE_DISCONNECT; |
| - | break; |
| - | } |
| - | smb_m = (const struct smb_nt_create_response *)msg; |
| - | req->fid = smb_swap16(smb_m->fid); |
| - | data->req.offset = 0; |
| - | if(data->state.upload) { |
| - | data->req.size = data->state.infilesize; |
| - | Curl_pgrsSetUploadSize(data, data->req.size); |
| - | next_state = SMB_UPLOAD; |
| - | } |
| - | else { |
| - | data->req.size = smb_swap64(smb_m->end_of_file); |
| - | if(data->req.size < 0) { |
| - | req->result = CURLE_WEIRD_SERVER_REPLY; |
| - | next_state = SMB_CLOSE; |
| - | } |
| - | else { |
| - | Curl_pgrsSetDownloadSize(data, data->req.size); |
| - | if(data->set.get_filetime) |
| - | get_posix_time(&data->info.filetime, smb_m->last_change_time); |
| - | next_state = SMB_DOWNLOAD; |
| - | } |
| - | } |
| - | break; |
| - | |
| - | case SMB_DOWNLOAD: |
| - | if(h->status || smbc->got < sizeof(struct smb_header) + 15) { |
| - | req->result = CURLE_RECV_ERROR; |
| - | next_state = SMB_CLOSE; |
| - | break; |
| - | } |
| - | len = Curl_read16_le((const unsigned char *)msg + |
| - | sizeof(struct smb_header) + 11); |
| - | off = Curl_read16_le((const unsigned char *)msg + |
| - | sizeof(struct smb_header) + 13); |
| - | if(len > 0) { |
| - | if(off + sizeof(unsigned int) + len > smbc->got) { |
| - | failf(data, "Invalid input packet"); |
| - | result = CURLE_RECV_ERROR; |
| - | } |
| - | else |
| - | result = Curl_client_write(data, CLIENTWRITE_BODY, |
| - | (char *)msg + off + sizeof(unsigned int), |
| - | len); |
| - | if(result) { |
| - | req->result = result; |
| - | next_state = SMB_CLOSE; |
| - | break; |
| - | } |
| - | } |
| - | data->req.offset += len; |
| - | next_state = (len < MAX_PAYLOAD_SIZE) ? SMB_CLOSE : SMB_DOWNLOAD; |
| - | break; |
| - | |
| - | case SMB_UPLOAD: |
| - | if(h->status || smbc->got < sizeof(struct smb_header) + 7) { |
| - | req->result = CURLE_UPLOAD_FAILED; |
| - | next_state = SMB_CLOSE; |
| - | break; |
| - | } |
| - | len = Curl_read16_le((const unsigned char *)msg + |
| - | sizeof(struct smb_header) + 5); |
| - | data->req.bytecount += len; |
| - | data->req.offset += len; |
| - | Curl_pgrs_upload_inc(data, len); |
| - | if(data->req.bytecount >= data->req.size) |
| - | next_state = SMB_CLOSE; |
| - | else |
| - | next_state = SMB_UPLOAD; |
| - | break; |
| - | |
| - | case SMB_CLOSE: |
| - | /* We do not care if the close failed, proceed to tree disconnect anyway */ |
| - | next_state = SMB_TREE_DISCONNECT; |
| - | break; |
| - | |
| - | case SMB_TREE_DISCONNECT: |
| - | next_state = SMB_DONE; |
| - | break; |
| - | |
| - | default: |
| - | smb_pop_message(smbc); |
| - | return CURLE_OK; /* ignore */ |
| - | } |
| - | |
| - | smb_pop_message(smbc); |
| - | |
| - | switch(next_state) { |
| - | case SMB_OPEN: |
| - | result = smb_send_open(data, smbc, req); |
| - | break; |
| - | |
| - | case SMB_DOWNLOAD: |
| - | result = smb_send_read(data, smbc, req); |
| - | break; |
| - | |
| - | case SMB_UPLOAD: |
| - | result = smb_send_write(data, smbc, req); |
| - | break; |
| - | |
| - | case SMB_CLOSE: |
| - | result = smb_send_close(data, smbc, req); |
| - | break; |
| - | |
| - | case SMB_TREE_DISCONNECT: |
| - | result = smb_send_tree_disconnect(data, smbc, req); |
| - | break; |
| - | |
| - | case SMB_DONE: |
| - | result = req->result; |
| - | *done = TRUE; |
| - | break; |
| - | |
| - | default: |
| - | break; |
| - | } |
| - | |
| - | if(result) { |
| - | CURL_TRC_M(data, "SMB: failed to send message"); |
| - | connclose(conn); |
| - | return result; |
| - | } |
| - | |
| - | request_state(data, next_state); |
| - | |
| - | return CURLE_OK; |
| - | } |
| - | |
| - | static CURLcode smb_pollset(struct Curl_easy *data, |
| - | struct easy_pollset *ps) |
| - | { |
| - | return Curl_pollset_add_inout(data, ps, data->conn->sock[FIRSTSOCKET]); |
| - | } |
| - | |
| - | static CURLcode smb_do(struct Curl_easy *data, bool *done) |
| - | { |
| - | struct connectdata *conn = data->conn; |
| - | struct smb_conn *smbc = Curl_conn_meta_get(conn, CURL_META_SMB_CONN); |
| - | |
| - | *done = FALSE; |
| - | if(!smbc) |
| - | return CURLE_FAILED_INIT; |
| - | if(smbc->share) |
| - | return CURLE_OK; |
| - | return CURLE_URL_MALFORMAT; |
| - | } |
| - | |
| - | /* |
| - | * SMB handler interface |
| - | */ |
| - | const struct Curl_protocol Curl_protocol_smb = { |
| - | smb_setup_connection, /* setup_connection */ |
| - | smb_do, /* do_it */ |
| - | ZERO_NULL, /* done */ |
| - | ZERO_NULL, /* do_more */ |
| - | smb_connect, /* connect_it */ |
| - | smb_connection_state, /* connecting */ |
| - | smb_request_state, /* doing */ |
| - | smb_pollset, /* proto_pollset */ |
| - | smb_pollset, /* doing_pollset */ |
| - | ZERO_NULL, /* domore_pollset */ |
| - | ZERO_NULL, /* perform_pollset */ |
| - | ZERO_NULL, /* disconnect */ |
| - | ZERO_NULL, /* write_resp */ |
| - | ZERO_NULL, /* write_resp_hd */ |
| - | ZERO_NULL, /* connection_is_dead */ |
| - | ZERO_NULL, /* attach connection */ |
| - | ZERO_NULL, /* follow */ |
| - | }; |
| - | |
| - | #endif /* CURL_ENABLE_SMB && USE_CURL_NTLM_CORE */ |
| @@ -1,31 +0,0 @@ | |
| - | #ifndef HEADER_CURL_SMB_H |
| - | #define HEADER_CURL_SMB_H |
| - | /*************************************************************************** |
| - | * _ _ ____ _ |
| - | * Project ___| | | | _ \| | |
| - | * / __| | | | |_) | | |
| - | * | (__| |_| | _ <| |___ |
| - | * \___|\___/|_| \_\_____| |
| - | * |
| - | * Copyright (C) Bill Nagel <[email protected]>, Exacq Technologies |
| - | * Copyright (C) Daniel Stenberg, <[email protected]>, et al. |
| - | * |
| - | * This software is licensed as described in the file COPYING, which |
| - | * you should have received as part of this distribution. The terms |
| - | * are also available at https://curl.se/docs/copyright.html. |
| - | * |
| - | * You may opt to use, copy, modify, merge, publish, distribute and/or sell |
| - | * copies of the Software, and permit persons to whom the Software is |
| - | * furnished to do so, under the terms of the COPYING file. |
| - | * |
| - | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| - | * KIND, either express or implied. |
| - | * |
| - | * SPDX-License-Identifier: curl |
| - | * |
| - | ***************************************************************************/ |
| - | #if defined(CURL_ENABLE_SMB) && defined(USE_CURL_NTLM_CORE) |
| - | extern const struct Curl_protocol Curl_protocol_smb; |
| - | #endif |
| - | |
| - | #endif /* HEADER_CURL_SMB_H */ |
| @@ -93,7 +93,6 @@ typedef CURLcode (Curl_recv)(struct Curl_easy *data, /* transfer */ | |
| #include "protocol.h" | |
| #include "ftp.h" | |
| #include "http.h" | |
| - | #include "smb.h" |
| #include "mqtt.h" | |
| #include "ftplistparser.h" | |
| #include "multihandle.h" | |
| @@ -345,12 +345,6 @@ static const char * const supported_protocols[] = { | |
| "scp", | |
| "sftp", | |
| #endif | |
| - | #if defined(CURL_ENABLE_SMB) && defined(USE_CURL_NTLM_CORE) |
| - | "smb", |
| - | # ifdef USE_SSL |
| - | "smbs", |
| - | # endif |
| - | #endif |
| #ifndef CURL_DISABLE_SMTP | |
| "smtp", | |
| #endif | |
| @@ -257,7 +257,6 @@ _ POP3 | |
| _ RTSP | |
| _ SCP if libssh2 is enabled | |
| _ SFTP if libssh2 is enabled | |
| - | _ SMB |
| _ SMTP | |
| _ TELNET | |
| _ TFTP | |
| @@ -175,8 +175,6 @@ my %knownprotos = ( | |
| 'RTSP' => 1, | |
| 'SCP' => 1, | |
| 'SFTP' => 1, | |
| - | 'SMB' => 1, |
| - | 'SMBS' => 1, |
| 'SMTP' => 1, | |
| 'SMTPS' => 1, | |
| 'TELNET' => 1, | |
| @@ -66,14 +66,12 @@ EXTRA_DIST = \ | |
| nghttpx.conf \ | |
| pathhelp.pm \ | |
| processhelp.pm \ | |
| - | requirements.txt \ |
| rtspserver.pl \ | |
| runner.pm \ | |
| runtests.pl \ | |
| secureserver.pl \ | |
| serverhelp.pm \ | |
| servers.pm \ | |
| - | smbserver.py \ |
| sshhelp.pm \ | |
| sshserver.pl \ | |
| testcurl.pl \ | |
| @@ -25,9 +25,6 @@ all: | |
| install: | |
| test: | |
| - | # The helper script ./scripts/testnum provides a set of available test |
| - | # numbers. |
| - | |
| # this list is in numerical order | |
| TESTCASES = \ | |
| test1 \ | |
| @@ -1472,7 +1469,6 @@ TESTCASES = \ | |
| test1448 \ | |
| test1449 \ | |
| test1450 \ | |
| - | test1451 \ |
| test1452 \ | |
| test1453 \ | |
| test1454 \ | |
| @@ -1740,7 +1736,6 @@ TESTCASES = \ | |
| test1847 \ | |
| test1848 \ | |
| test1849 \ | |
| - | test1850 \ |
| test1851 \ | |
| test1862 \ | |
| test1900 \ | |
| @@ -1,38 +0,0 @@ | |
| - | <?xml version="1.0" encoding="US-ASCII"?> |
| - | <testcase> |
| - | <info> |
| - | <keywords> |
| - | SMB |
| - | </keywords> |
| - | </info> |
| - | |
| - | # Server-side |
| - | <reply> |
| - | <data nocheck="yes"> |
| - | Basic SMB test complete |
| - | </data> |
| - | </reply> |
| - | |
| - | # Client-side |
| - | <client> |
| - | <server> |
| - | smb |
| - | </server> |
| - | <features> |
| - | smb |
| - | </features> |
| - | <name> |
| - | Basic SMB request |
| - | </name> |
| - | <command> |
| - | -u 'curltest:curltest' smb://%HOSTIP:%SMBPORT/TESTS/%TESTNUMBER |
| - | </command> |
| - | </client> |
| - | |
| - | # Verify data after the test has been "shot" |
| - | <verify> |
| - | <stdout> |
| - | Basic SMB test complete |
| - | </stdout> |
| - | </verify> |
| - | </testcase> |
| @@ -18,7 +18,7 @@ Curl_get_scheme unit test | |
| <verify> | |
| <stdout mode="text"> | |
| - | 547 invokes |
| + | 541 invokes |
| </stdout> | |
| </verify> | |
| </testcase> | |
| @@ -1,39 +0,0 @@ | |
| - | <?xml version="1.0" encoding="US-ASCII"?> |
| - | <testcase> |
| - | <info> |
| - | <keywords> |
| - | SMB |
| - | </keywords> |
| - | </info> |
| - | |
| - | # Server-side |
| - | <reply> |
| - | <data nocheck="yes"> |
| - | Basic SMB test complete |
| - | </data> |
| - | </reply> |
| - | |
| - | # Client-side |
| - | <client> |
| - | <server> |
| - | smb |
| - | </server> |
| - | <features> |
| - | smb |
| - | </features> |
| - | <name> |
| - | Two SMB requests in the same command line |
| - | </name> |
| - | <command> |
| - | -u 'curltest:curltest' smb://%HOSTIP:%SMBPORT/TESTS/%TESTNUMBER smb://%HOSTIP:%SMBPORT/TESTS/%TESTNUMBER |
| - | </command> |
| - | </client> |
| - | |
| - | # Verify data after the test has been "shot" |
| - | <verify> |
| - | <stdout> |
| - | Basic SMB test complete |
| - | Basic SMB test complete |
| - | </stdout> |
| - | </verify> |
| - | </testcase> |
| @@ -1,5 +0,0 @@ | |
| - | # Copyright (C) Daniel Stenberg, <[email protected]>, et al. |
| - | # |
| - | # SPDX-License-Identifier: curl |
| - | |
| - | impacket==0.13.1 |
| @@ -123,7 +123,7 @@ sub servername_str { | |
| $proto = uc($proto) if($proto); | |
| die "unsupported protocol: '$proto'" unless($proto && | |
| - | ($proto =~ /^(((DNS|FTP|HTTP|HTTP\/2|HTTP\/3|IMAP|POP3|GOPHER|SMTP|HTTPS-MTLS)S?)|(TFTP|SFTP|SOCKS|SSH|RTSP|DICT|SMB|SMBS|TELNET|MQTT|MQTTS))$/)); |
| + | ($proto =~ /^(((DNS|FTP|HTTP|HTTP\/2|HTTP\/3|IMAP|POP3|GOPHER|SMTP|HTTPS-MTLS)S?)|(TFTP|SFTP|SOCKS|SSH|RTSP|DICT|TELNET|MQTT|MQTTS))$/)); |
| $ipver = (not $ipver) ? 'ipv4' : lc($ipver); | |
| die "unsupported IP version: '$ipver'" unless($ipver && | |
| @@ -235,7 +235,7 @@ sub init_serverpidfile_hash { | |
| } | |
| } | |
| for my $proto (('tftp', 'sftp', 'socks', 'ssh', 'rtsp', | |
| - | 'dict', 'smb', 'smbs', 'telnet', 'mqtt', 'mqtts', |
| + | 'dict', 'telnet', 'mqtt', 'mqtts', |
| 'https-mtls', 'dns')) { | |
| for my $ipvnum ((4, 6)) { | |
| for my $idnum ((1, 2)) { | |
| @@ -797,66 +797,6 @@ sub verifypid { | |
| return $pid; | |
| } | |
| - | ####################################################################### |
| - | # Verify that the server that runs on $ip, $port is our server. This also |
| - | # implies that we can speak with it, as there might be occasions when the |
| - | # server runs fine but we cannot talk to it ("Failed to connect to ::1: Cannot |
| - | # assign requested address") |
| - | # |
| - | sub verifysmb { |
| - | my ($proto, $ipvnum, $idnum, $ip, $port) = @_; |
| - | my $server = servername_id($proto, $ipvnum, $idnum); |
| - | my $time = time(); |
| - | my $extra = ""; |
| - | |
| - | my $verifylog = "$LOGDIR/". |
| - | servername_canon($proto, $ipvnum, $idnum) .'_verify.log'; |
| - | unlink($verifylog) if(-f $verifylog); |
| - | |
| - | my $flags = "--max-time $server_response_maxtime "; |
| - | $flags .= "--silent "; |
| - | $flags .= "--verbose "; |
| - | $flags .= "--globoff "; |
| - | $flags .= "-u 'curltest:curltest' "; |
| - | $flags .= $extra; |
| - | $flags .= "\"$proto://$ip:$port/SERVER/verifiedserver\""; |
| - | |
| - | my $cmd = exerunner() . "$VCURL $flags 2>$verifylog"; |
| - | |
| - | # check if this is our server running on this port: |
| - | logmsg "RUN: $cmd\n" if($verbose); |
| - | my @data = runclientoutput($cmd); |
| - | |
| - | my $res = $? >> 8; # rotate the result |
| - | if($res & 128) { |
| - | logmsg "RUN: curl command died with a coredump\n"; |
| - | return -1; |
| - | } |
| - | |
| - | my $pid = 0; |
| - | foreach my $line (@data) { |
| - | if($line =~ /WE ROOLZ: (\d+)/) { |
| - | # this is our test server with a known pid! |
| - | $pid = 0+$1; |
| - | last; |
| - | } |
| - | } |
| - | if($pid <= 0 && @data && $data[0]) { |
| - | # this is not a known server |
| - | logmsg "RUN: Unknown server on our $server port: $port\n"; |
| - | return 0; |
| - | } |
| - | # we can/should use the time it took to verify the server as a measure |
| - | # on how fast/slow this host is. |
| - | my $took = int(0.5+time()-$time); |
| - | |
| - | if($verbose) { |
| - | logmsg "RUN: Verifying our test $server server took $took seconds\n"; |
| - | } |
| - | |
| - | return $pid; |
| - | } |
| - | |
| ####################################################################### | |
| # Verify that the server that runs on $ip, $port is our server. This also | |
| # implies that we can speak with it, as there might be occasions when the | |
| @@ -950,7 +890,6 @@ my %protofunc = ('http' => \&verifyhttp, | |
| 'socks5unix' => \&verifypid, | |
| 'gopher' => \&verifyhttp, | |
| 'dict' => \&verifyftp, | |
| - | 'smb' => \&verifysmb, |
| 'telnet' => \&verifytelnet); | |
| ####################################################################### | |
| @@ -1973,67 +1912,6 @@ sub rundictserver { | |
| return (0+!$dictpid, $dictpid, $pid2, $port); | |
| } | |
| - | ####################################################################### |
| - | # start the SMB server |
| - | # |
| - | sub runsmbserver { |
| - | my ($verb, $alt) = @_; |
| - | my $proto = "smb"; |
| - | my $ip = $HOSTIP; |
| - | my $ipvnum = 4; |
| - | my $idnum = 1; |
| - | |
| - | if($alt eq "ipv6") { |
| - | # No IPv6 |
| - | } |
| - | |
| - | my $server = servername_id($proto, $ipvnum, $idnum); |
| - | |
| - | my $pidfile = $serverpidfile{$server}; |
| - | |
| - | # do not retry if the server does not work |
| - | if($doesntrun{$pidfile}) { |
| - | return (2, 0, 0, 0); |
| - | } |
| - | |
| - | my $pid = processexists($pidfile); |
| - | if($pid > 0) { |
| - | stopserver($server, $pid); |
| - | } |
| - | unlink($pidfile) if(-f $pidfile); |
| - | |
| - | my $srvrname = servername_str($proto, $ipvnum, $idnum); |
| - | my $logfile = server_logfilename($LOGDIR, $proto, $ipvnum, $idnum); |
| - | |
| - | my $flags = ""; |
| - | $flags .= "--verbose 1 " if($debugprotocol); |
| - | $flags .= "--pidfile \"$pidfile\" --logfile \"$logfile\" "; |
| - | $flags .= "--id $idnum " if($idnum > 1); |
| - | $flags .= "--srcdir \"$srcdir\" "; |
| - | $flags .= "--host $HOSTIP"; |
| - | |
| - | my $port = getfreeport($ipvnum); |
| - | my $aflags = "--port $port $flags"; |
| - | my $cmd = "$srcdir/smbserver.py $aflags"; |
| - | my ($smbpid, $pid2) = startnew($cmd, $pidfile, 15, 0); |
| - | |
| - | if($smbpid <= 0 || !pidexists($smbpid)) { |
| - | # it is NOT alive |
| - | stopserver($server, $pid2); |
| - | $doesntrun{$pidfile} = 1; |
| - | $smbpid = $pid2 = 0; |
| - | logmsg "RUN: failed to start the $srvrname server\n"; |
| - | return (3, 0, 0, 0); |
| - | } |
| - | $doesntrun{$pidfile} = 0; |
| - | |
| - | if($verb) { |
| - | logmsg "RUN: $srvrname server PID $smbpid port $port\n"; |
| - | } |
| - | |
| - | return (0+!$smbpid, $smbpid, $pid2, $port); |
| - | } |
| - | |
| ####################################################################### | |
| # start the telnet server | |
| # | |
| @@ -2817,17 +2695,6 @@ sub startservers { | |
| $run{'dict'} = "$pid $pid2"; | |
| } | |
| } | |
| - | elsif($what eq "smb") { |
| - | if(!$run{'smb'}) { |
| - | ($serr, $pid, $pid2, $PORT{"smb"}) = runsmbserver($verbose, ""); |
| - | if($pid <= 0) { |
| - | return ("failed starting SMB server", $serr); |
| - | } |
| - | logmsg sprintf ("* pid SMB => %d %d\n", $pid, $pid2) |
| - | if($verbose); |
| - | $run{'smb'} = "$pid $pid2"; |
| - | } |
| - | } |
| elsif($what eq "telnet") { | |
| if(!$run{'telnet'}) { | |
| ($serr, $pid, $pid2, $PORT{"telnet"}) = | |
| @@ -2930,7 +2797,6 @@ sub subvariables { | |
| 'NOLISTEN', | |
| 'POP3', 'POP36', 'POP3S', | |
| 'RTSP', 'RTSP6', | |
| - | 'SMB', 'SMBS', |
| 'SMTP', 'SMTP6', 'SMTPS', | |
| 'SOCKS', | |
| 'SSH', | |
| @@ -1,440 +0,0 @@ | |
| - | #!/usr/bin/env python3 |
| - | # |
| - | # Project ___| | | | _ \| | |
| - | # / __| | | | |_) | | |
| - | # | (__| |_| | _ <| |___ |
| - | # \___|\___/|_| \_\_____| |
| - | # |
| - | # Copyright (C) Daniel Stenberg, <[email protected]>, et al. |
| - | # |
| - | # This software is licensed as described in the file COPYING, which |
| - | # you should have received as part of this distribution. The terms |
| - | # are also available at https://curl.se/docs/copyright.html. |
| - | # |
| - | # You may opt to use, copy, modify, merge, publish, distribute and/or sell |
| - | # copies of the Software, and permit persons to whom the Software is |
| - | # furnished to do so, under the terms of the COPYING file. |
| - | # |
| - | # This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| - | # KIND, either express or implied. |
| - | # |
| - | # SPDX-License-Identifier: curl |
| - | # |
| - | """Server for testing SMB.""" |
| - | |
| - | import argparse |
| - | import configparser |
| - | import importlib.util |
| - | import logging |
| - | import os |
| - | import signal |
| - | import sys |
| - | import tempfile |
| - | import threading |
| - | |
| - | # Import our curl test data helper |
| - | from util import ClosingFileHandler, TestData |
| - | |
| - | # impacket needs to be installed in the Python environment |
| - | if importlib.util.find_spec('impacket') is None: |
| - | sys.stderr.write( |
| - | 'Warning: Python package impacket is required for smb testing; ' |
| - | 'use pip or your package manager to install it\n') |
| - | sys.exit(1) |
| - | |
| - | from impacket import smb as imp_smb |
| - | from impacket import smbserver as imp_smbserver |
| - | from impacket.nt_errors import STATUS_ACCESS_DENIED, STATUS_NO_SUCH_FILE, STATUS_SUCCESS |
| - | |
| - | log = logging.getLogger(__name__) |
| - | SERVER_MAGIC = "SERVER_MAGIC" |
| - | TESTS_MAGIC = "TESTS_MAGIC" |
| - | VERIFIED_REQ = "verifiedserver" |
| - | VERIFIED_RSP = "WE ROOLZ: {pid}\n" |
| - | |
| - | |
| - | class ShutdownHandler(threading.Thread): |
| - | """ |
| - | Cleanly shut down the SMB server. |
| - | |
| - | This can only be done from another thread while the server is in |
| - | serve_forever(), so a thread is spawned here that waits for a shutdown |
| - | signal before doing its thing. Use in a with statement around the |
| - | serve_forever() call. |
| - | """ |
| - | |
| - | def __init__(self, server): |
| - | super().__init__() |
| - | self.server = server |
| - | self.shutdown_event = threading.Event() |
| - | |
| - | def __enter__(self): |
| - | self.start() |
| - | signal.signal(signal.SIGINT, self._sighandler) |
| - | signal.signal(signal.SIGTERM, self._sighandler) |
| - | |
| - | def __exit__(self, *_): |
| - | # Call for shutdown in case it was not done already |
| - | self.shutdown_event.set() |
| - | # Wait for thread, and therefore also the server, to finish |
| - | self.join() |
| - | # Uninstall our signal handlers |
| - | signal.signal(signal.SIGINT, signal.SIG_DFL) |
| - | signal.signal(signal.SIGTERM, signal.SIG_DFL) |
| - | # Delete any temporary files created by the server during its run |
| - | log.info("Deleting %d temporary file(s)", len(self.server.tmpfiles)) |
| - | for f in self.server.tmpfiles: |
| - | os.unlink(f) |
| - | |
| - | def _sighandler(self, _signum, _frame): |
| - | # Wake up the cleanup task |
| - | self.shutdown_event.set() |
| - | |
| - | def run(self): |
| - | # Wait for shutdown signal |
| - | self.shutdown_event.wait() |
| - | # Notify the server to shut down |
| - | self.server.shutdown() |
| - | |
| - | |
| - | def smbserver(options): |
| - | """Start up a TCP SMB server that serves forever.""" |
| - | if options.pidfile: |
| - | pid = os.getpid() |
| - | # see tests/server/util.c function write_pidfile |
| - | if os.name == "nt": |
| - | pid += 4194304 |
| - | with open(options.pidfile, "w") as f: |
| - | f.write(str(pid)) |
| - | |
| - | # Here we write a mini config for the server |
| - | smb_config = configparser.ConfigParser() |
| - | smb_config.add_section("global") |
| - | smb_config.set("global", "server_name", "SERVICE") |
| - | smb_config.set("global", "server_os", "UNIX") |
| - | smb_config.set("global", "server_domain", "WORKGROUP") |
| - | smb_config.set("global", "log_file", "None") |
| - | smb_config.set("global", "credentials_file", "") |
| - | |
| - | # We need a share which allows us to test that the server is running |
| - | smb_config.add_section("SERVER") |
| - | smb_config.set("SERVER", "comment", "server function") |
| - | smb_config.set("SERVER", "read only", "yes") |
| - | smb_config.set("SERVER", "share type", "0") |
| - | smb_config.set("SERVER", "path", SERVER_MAGIC) |
| - | |
| - | # Have a share for tests. These files are auto-generated from the |
| - | # test input. |
| - | smb_config.add_section("TESTS") |
| - | smb_config.set("TESTS", "comment", "tests") |
| - | smb_config.set("TESTS", "read only", "yes") |
| - | smb_config.set("TESTS", "share type", "0") |
| - | smb_config.set("TESTS", "path", TESTS_MAGIC) |
| - | |
| - | if not options.srcdir or not os.path.isdir(options.srcdir): |
| - | raise ScriptError("--srcdir is mandatory") |
| - | |
| - | test_data_dir = os.path.join(options.srcdir, "data") |
| - | |
| - | smb_server = TestSmbServer((options.host, options.port), |
| - | config_parser=smb_config, |
| - | test_data_directory=test_data_dir) |
| - | log.info("[SMB] setting up SMB server on port %s", options.port) |
| - | smb_server.processConfigFile() |
| - | |
| - | # Start a thread that cleanly shuts down the server on a signal |
| - | with ShutdownHandler(smb_server): |
| - | # This blocks until smb_server.shutdown() is called |
| - | smb_server.serve_forever() |
| - | |
| - | return 0 |
| - | |
| - | |
| - | class TestSmbServer(imp_smbserver.SMBSERVER): |
| - | """ |
| - | Test server for SMB. |
| - | |
| - | It subclasses the impacket SMBSERVER and provides test functionality. |
| - | """ |
| - | |
| - | def __init__(self, |
| - | address, |
| - | config_parser=None, |
| - | test_data_directory=None): |
| - | imp_smbserver.SMBSERVER.__init__(self, |
| - | address, |
| - | config_parser=config_parser) |
| - | self.tmpfiles = [] |
| - | |
| - | # Set up a test data object so we can get test data later. |
| - | self.ctd = TestData(test_data_directory) |
| - | |
| - | # Override smbComNtCreateAndX so we can pretend to have files which |
| - | # do not exist. |
| - | self.hookSmbCommand(imp_smb.SMB.SMB_COM_NT_CREATE_ANDX, |
| - | self.create_and_x) |
| - | |
| - | def create_and_x(self, conn_id, smb_server, smb_command, recv_packet): |
| - | """ |
| - | Our version of smbComNtCreateAndX. |
| - | |
| - | It looks for special test files and fools the rest of the framework |
| - | into opening them as if they were normal files. |
| - | """ |
| - | conn_data = smb_server.getConnectionData(conn_id) |
| - | |
| - | # Wrap processing in a try block which allows us to throw SmbError |
| - | # to control the flow. |
| - | try: |
| - | ncax_params = imp_smb.SMBNtCreateAndX_Parameters( |
| - | smb_command["Parameters"]) |
| - | |
| - | path = self.get_share_path(conn_data, |
| - | ncax_params["RootFid"], |
| - | recv_packet["Tid"]) |
| - | log.info("[SMB] Requested share path: %s", path) |
| - | |
| - | disposition = ncax_params["Disposition"] |
| - | log.debug("[SMB] Requested disposition: %s", disposition) |
| - | |
| - | # Currently we only support reading files. |
| - | if disposition != imp_smb.FILE_OPEN: |
| - | raise SmbError(STATUS_ACCESS_DENIED, "Only support reading files") |
| - | |
| - | # Check to see if the path we were given is actually a |
| - | # magic path which needs generating on the fly. |
| - | if path not in [SERVER_MAGIC, TESTS_MAGIC]: |
| - | # Pass the command onto the original handler. |
| - | return imp_smbserver.SMBCommands.smbComNtCreateAndX(conn_id, |
| - | smb_server, |
| - | smb_command, |
| - | recv_packet) |
| - | |
| - | flags2 = recv_packet["Flags2"] |
| - | ncax_data = imp_smb.SMBNtCreateAndX_Data(flags=flags2, |
| - | data=smb_command["Data"]) |
| - | requested_file = imp_smbserver.decodeSMBString( |
| - | flags2, |
| - | ncax_data["FileName"]) |
| - | log.debug("[SMB] User requested file '%s'", requested_file) |
| - | |
| - | if path == SERVER_MAGIC: |
| - | fid, full_path = self.get_server_path(requested_file) |
| - | else: |
| - | assert path == TESTS_MAGIC |
| - | fid, full_path = self.get_test_path(requested_file) |
| - | |
| - | self.tmpfiles.append(full_path) |
| - | |
| - | resp_params = imp_smb.SMBNtCreateAndXResponse_Parameters() |
| - | resp_data = "" |
| - | |
| - | # Simple way to generate a fid |
| - | if len(conn_data["OpenedFiles"]) == 0: |
| - | fakefid = 1 |
| - | else: |
| - | fakefid = max(conn_data["OpenedFiles"].keys()) + 1 |
| - | resp_params["Fid"] = fakefid |
| - | resp_params["CreateAction"] = disposition |
| - | |
| - | if os.path.isdir(path): |
| - | resp_params[ |
| - | "FileAttributes"] = imp_smb.SMB_FILE_ATTRIBUTE_DIRECTORY |
| - | resp_params["IsDirectory"] = 1 |
| - | else: |
| - | resp_params["IsDirectory"] = 0 |
| - | resp_params["FileAttributes"] = ncax_params["FileAttributes"] |
| - | |
| - | # Get this file's information |
| - | resp_info, error_code = imp_smbserver.queryPathInformation( |
| - | os.path.dirname(full_path), os.path.basename(full_path), |
| - | level=imp_smb.SMB_QUERY_FILE_ALL_INFO) |
| - | |
| - | if error_code != STATUS_SUCCESS: |
| - | raise SmbError(error_code, "Failed to query path info") |
| - | |
| - | resp_params["CreateTime"] = resp_info["CreationTime"] |
| - | resp_params["LastAccessTime"] = resp_info[ |
| - | "LastAccessTime"] |
| - | resp_params["LastWriteTime"] = resp_info["LastWriteTime"] |
| - | resp_params["LastChangeTime"] = resp_info[ |
| - | "LastChangeTime"] |
| - | resp_params["FileAttributes"] = resp_info[ |
| - | "ExtFileAttributes"] |
| - | resp_params["AllocationSize"] = resp_info[ |
| - | "AllocationSize"] |
| - | resp_params["EndOfFile"] = resp_info["EndOfFile"] |
| - | |
| - | # Let's store the fid for the connection |
| - | # smbServer.log("Create file %s, mode:0x%x" % (pathName, mode)) |
| - | conn_data["OpenedFiles"][fakefid] = {} |
| - | conn_data["OpenedFiles"][fakefid]["FileHandle"] = fid |
| - | conn_data["OpenedFiles"][fakefid]["FileName"] = path |
| - | conn_data["OpenedFiles"][fakefid]["DeleteOnClose"] = False |
| - | |
| - | except SmbError as s: |
| - | log.debug("[SMB] SmbError hit: %s", s) |
| - | error_code = s.error_code |
| - | resp_params = "" |
| - | resp_data = "" |
| - | |
| - | resp_cmd = imp_smb.SMBCommand(imp_smb.SMB.SMB_COM_NT_CREATE_ANDX) |
| - | resp_cmd["Parameters"] = resp_params |
| - | resp_cmd["Data"] = resp_data |
| - | smb_server.setConnectionData(conn_id, conn_data) |
| - | |
| - | return [resp_cmd], None, error_code |
| - | |
| - | def get_share_path(self, conn_data, root_fid, tid): |
| - | conn_shares = conn_data["ConnectedShares"] |
| - | |
| - | if tid in conn_shares: |
| - | if root_fid > 0: |
| - | # If we have a rootFid, the path is relative to that fid |
| - | path = conn_data["OpenedFiles"][root_fid]["FileName"] |
| - | log.debug(f'RootFid present {path}!') |
| - | return path |
| - | |
| - | if "path" in conn_shares[tid]: |
| - | return conn_shares[tid]["path"] |
| - | |
| - | raise SmbError(STATUS_ACCESS_DENIED, "Connection share had no path") |
| - | raise SmbError(imp_smbserver.STATUS_SMB_BAD_TID, "TID was invalid") |
| - | |
| - | def get_server_path(self, requested_filename): |
| - | log.debug("[SMB] Get server path '%s'", requested_filename) |
| - | |
| - | if requested_filename != VERIFIED_REQ: |
| - | raise SmbError(STATUS_NO_SUCH_FILE, "Could not find the file") |
| - | |
| - | fid, filename = tempfile.mkstemp() |
| - | log.debug("[SMB] Created %s (%d) for storing '%s'", |
| - | filename, fid, requested_filename) |
| - | |
| - | contents = b'' |
| - | |
| - | if requested_filename == VERIFIED_REQ: |
| - | log.debug("[SMB] Verifying server is alive") |
| - | pid = os.getpid() |
| - | # see tests/server/util.c function write_pidfile |
| - | if os.name == "nt": |
| - | pid += 4194304 |
| - | contents = VERIFIED_RSP.format(pid=pid).encode('utf-8') |
| - | |
| - | self.write_to_fid(fid, contents) |
| - | return fid, filename |
| - | |
| - | def write_to_fid(self, fid, contents): |
| - | # Write the contents to file descriptor |
| - | os.write(fid, contents) |
| - | os.fsync(fid) |
| - | |
| - | # Rewind the file to the beginning so a read gets us the contents |
| - | os.lseek(fid, 0, os.SEEK_SET) |
| - | |
| - | def get_test_path(self, requested_filename): |
| - | log.info("[SMB] Get reply data from 'test%s'", requested_filename) |
| - | |
| - | fid, filename = tempfile.mkstemp() |
| - | log.debug("[SMB] Created %s (%d) for storing test '%s'", |
| - | filename, fid, requested_filename) |
| - | |
| - | try: |
| - | contents = self.ctd.get_test_data(requested_filename).encode('utf-8') |
| - | self.write_to_fid(fid, contents) |
| - | return fid, filename |
| - | |
| - | except Exception as e: |
| - | log.exception("Failed to make test file") |
| - | raise SmbError(STATUS_NO_SUCH_FILE, "Failed to make test file") from e |
| - | |
| - | |
| - | class SmbError(Exception): |
| - | def __init__(self, error_code, error_message): |
| - | super().__init__(error_message) |
| - | self.error_code = error_code |
| - | |
| - | |
| - | class ScriptRC: |
| - | """Enum for script return codes.""" |
| - | |
| - | SUCCESS = 0 |
| - | FAILURE = 1 |
| - | EXCEPTION = 2 |
| - | |
| - | |
| - | class ScriptError(Exception): |
| - | pass |
| - | |
| - | |
| - | def get_options(): |
| - | parser = argparse.ArgumentParser() |
| - | |
| - | parser.add_argument("--port", action="store", default=9017, |
| - | type=int, help="port to listen on") |
| - | parser.add_argument("--host", action="store", default="127.0.0.1", |
| - | help="host to listen on") |
| - | parser.add_argument("--verbose", action="store", type=int, default=0, |
| - | help="verbose output") |
| - | parser.add_argument("--pidfile", action="store", |
| - | help="filename for the PID") |
| - | parser.add_argument("--logfile", action="store", |
| - | help="filename for the log") |
| - | parser.add_argument("--srcdir", action="store", help="test directory") |
| - | parser.add_argument("--id", action="store", help="server ID") |
| - | parser.add_argument("--ipv4", action="store_true", default=0, |
| - | help="IPv4 flag") |
| - | |
| - | return parser.parse_args() |
| - | |
| - | |
| - | def setup_logging(options): |
| - | """Set up logging from the command line options.""" |
| - | root_logger = logging.getLogger() |
| - | add_stdout = False |
| - | |
| - | formatter = logging.Formatter("%(asctime)s %(levelname)-5.5s %(message)s") |
| - | |
| - | # Write out to a logfile |
| - | if options.logfile: |
| - | handler = ClosingFileHandler(options.logfile) |
| - | handler.setFormatter(formatter) |
| - | handler.setLevel(logging.DEBUG) |
| - | root_logger.addHandler(handler) |
| - | else: |
| - | # The logfile was not specified. Add a stdout logger. |
| - | add_stdout = True |
| - | |
| - | if options.verbose: |
| - | # Add a stdout logger as well in verbose mode |
| - | root_logger.setLevel(logging.DEBUG) |
| - | add_stdout = True |
| - | else: |
| - | root_logger.setLevel(logging.WARNING) |
| - | |
| - | if add_stdout: |
| - | stdout_handler = logging.StreamHandler(sys.stdout) |
| - | stdout_handler.setFormatter(formatter) |
| - | stdout_handler.setLevel(logging.DEBUG) |
| - | root_logger.addHandler(stdout_handler) |
| - | |
| - | |
| - | if __name__ == '__main__': |
| - | # Get the options from the user. |
| - | options = get_options() |
| - | |
| - | # Setup logging using the user options |
| - | setup_logging(options) |
| - | |
| - | # Run main script. |
| - | try: |
| - | rc = smbserver(options) |
| - | except Exception: |
| - | log.exception('Error in SMB server') |
| - | rc = ScriptRC.EXCEPTION |
| - | |
| - | if options.pidfile and os.path.isfile(options.pidfile): |
| - | os.unlink(options.pidfile) |
| - | |
| - | log.info("[SMB] Returning %d", rc) |
| - | sys.exit(rc) |
| @@ -38,18 +38,15 @@ static CURLcode test_unit1627(const char *arg) | |
| /* all upper */ | |
| "DICT", "FILE", "FTP", "FTPS", "GOPHER", "GOPHERS", "HTTP", "HTTPS", | |
| "IMAP", "IMAPS", "LDAP", "LDAPS", "MQTT", "MQTTS", "POP3", "POP3S", | |
| - | "RTSP", "SCP", "SFTP", "SMB", "SMBS", "SMTP", "SMTPS", |
| - | "TELNET", "TFTP", "WS", "WSS", |
| + | "RTSP", "SCP", "SFTP", "SMTP", "SMTPS", "TELNET", "TFTP", "WS", "WSS", |
| /* all lower */ | |
| "dict", "file", "ftp", "ftps", "gopher", "gophers", "http", "https", | |
| "imap", "imaps", "ldap", "ldaps", "mqtt", "mqtts", "pop3", "pop3s", | |
| - | "rtsp", "scp", "sftp", "smb", "smbs", "smtp", "smtps", |
| - | "telnet", "tftp", "ws", "wss", |
| + | "rtsp", "scp", "sftp", "smtp", "smtps", "telnet", "tftp", "ws", "wss", |
| /* mixed */ | |
| "diCt", "fIle", "Ftp", "ftpS", "Gopher", "gOphers", "htTp", "httPs", | |
| "imAP", "imaPS", "LDap", "LDAps", "mQTT", "mqtTS", "pOP3", "pOP3s", | |
| - | "RtsP", "ScP", "SFtP", "Smb", "smBS", "sMTP", "SMTPs", |
| - | "TELNEt", "tFTP", "Ws", "wSS", |
| + | "RtsP", "ScP", "SFtP", "sMTP", "SMTPs", "TELNEt", "tFTP", "Ws", "wSS", |
| "SOCKS", "SOCKS4", "SOCKS5", "SOCKS4A", "SOCKS5H", | |
| "socks", "socks4", "socks5", "socks4a", "socks5h", | |