summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--.gitmodules3
-rw-r--r--CMakeLists.txt13
-rw-r--r--cmake/modules/FindGSSAPI.cmake325
m---------libssh0
-rw-r--r--patch/libssh-0.10.4.patch157
6 files changed, 497 insertions, 2 deletions
diff --git a/.gitignore b/.gitignore
index b86d665..f2c15e5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
build
+libssh-installed
.*.swp
diff --git a/.gitmodules b/.gitmodules
new file mode 100644
index 0000000..0ea1fcd
--- /dev/null
+++ b/.gitmodules
@@ -0,0 +1,3 @@
+[submodule "libssh"]
+ path = libssh
+ url = https://git.libssh.org/projects/libssh.git
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 26f6267..af022a3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -7,17 +7,26 @@ project(mscp
LANGUAGES C)
set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DDEBUG")
+list(APPEND CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/modules)
if(APPLE)
list(APPEND CMAKE_PREFIX_PATH /usr/local) # intel mac homebrew prefix
list(APPEND CMAKE_PREFIX_PATH /opt/homebrew) # arm mac homebrew prefix
endif() # APPLE
-find_package(libssh REQUIRED)
add_executable(mscp src/main.c src/platform.c src/ssh.c src/file.c src/pprint.c)
target_include_directories(mscp PUBLIC ./src)
-target_link_libraries(mscp ssh pthread m)
+if (LIBSSH_PATH)
+ find_package(GSSAPI)
+ target_include_directories(mscp PUBLIC ${LIBSSH_PATH}/include)
+ target_link_directories(mscp PRIVATE ${LIBSSH_PATH}/lib)
+ target_link_libraries(mscp pthread m libssh.a ssl crypto z ${GSSAPI_LIBRARIES})
+else()
+ find_package(libssh REQUIRED)
+ target_link_libraries(mscp pthread m ssh)
+endif()
+
target_compile_definitions(mscp PUBLIC _VERSION="${PROJECT_VERSION}")
install(TARGETS mscp
diff --git a/cmake/modules/FindGSSAPI.cmake b/cmake/modules/FindGSSAPI.cmake
new file mode 100644
index 0000000..4c3f44b
--- /dev/null
+++ b/cmake/modules/FindGSSAPI.cmake
@@ -0,0 +1,325 @@
+# - Try to find GSSAPI
+# Once done this will define
+#
+# KRB5_CONFIG - Path to krb5-config
+# GSSAPI_ROOT_DIR - Set this variable to the root installation of GSSAPI
+#
+# Read-Only variables:
+# GSSAPI_FLAVOR_MIT - set to TURE if MIT Kerberos has been found
+# GSSAPI_FLAVOR_HEIMDAL - set to TRUE if Heimdal Keberos has been found
+# GSSAPI_FOUND - system has GSSAPI
+# GSSAPI_INCLUDE_DIR - the GSSAPI include directory
+# GSSAPI_LIBRARIES - Link these to use GSSAPI
+# GSSAPI_DEFINITIONS - Compiler switches required for using GSSAPI
+#
+#=============================================================================
+# Copyright (c) 2013 Andreas Schneider <asn@cryptomilk.org>
+#
+# Distributed under the OSI-approved BSD License (the "License");
+# see accompanying file Copyright.txt for details.
+#
+# This software is distributed WITHOUT ANY WARRANTY; without even the
+# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+# See the License for more information.
+#=============================================================================
+#
+
+find_path(GSSAPI_ROOT_DIR
+ NAMES
+ include/gssapi.h
+ include/gssapi/gssapi.h
+ HINTS
+ ${_GSSAPI_ROOT_HINTS}
+ PATHS
+ ${_GSSAPI_ROOT_PATHS}
+)
+mark_as_advanced(GSSAPI_ROOT_DIR)
+
+if (UNIX)
+ find_program(KRB5_CONFIG
+ NAMES
+ krb5-config
+ PATHS
+ ${GSSAPI_ROOT_DIR}/bin
+ /opt/local/bin)
+ mark_as_advanced(KRB5_CONFIG)
+
+ if (KRB5_CONFIG)
+ # Check if we have MIT KRB5
+ execute_process(
+ COMMAND
+ ${KRB5_CONFIG} --vendor
+ RESULT_VARIABLE
+ _GSSAPI_VENDOR_RESULT
+ OUTPUT_VARIABLE
+ _GSSAPI_VENDOR_STRING)
+
+ if ((_GSSAPI_VENDOR_STRING MATCHES ".*Massachusetts.*") OR (_GSSAPI_VENDOR_STRING
+ MATCHES ".*MITKerberosShim.*"))
+ set(GSSAPI_FLAVOR_MIT TRUE)
+ else()
+ execute_process(
+ COMMAND
+ ${KRB5_CONFIG} --libs gssapi
+ RESULT_VARIABLE
+ _GSSAPI_LIBS_RESULT
+ OUTPUT_VARIABLE
+ _GSSAPI_LIBS_STRING)
+
+ if (_GSSAPI_LIBS_STRING MATCHES ".*roken.*")
+ set(GSSAPI_FLAVOR_HEIMDAL TRUE)
+ endif()
+ endif()
+
+ # Get the include dir
+ execute_process(
+ COMMAND
+ ${KRB5_CONFIG} --cflags gssapi
+ RESULT_VARIABLE
+ _GSSAPI_INCLUDE_RESULT
+ OUTPUT_VARIABLE
+ _GSSAPI_INCLUDE_STRING)
+ string(REGEX REPLACE "(\r?\n)+$" "" _GSSAPI_INCLUDE_STRING "${_GSSAPI_INCLUDE_STRING}")
+ string(REGEX REPLACE " *-I" "" _GSSAPI_INCLUDEDIR "${_GSSAPI_INCLUDE_STRING}")
+ endif()
+
+ if (NOT GSSAPI_FLAVOR_MIT AND NOT GSSAPI_FLAVOR_HEIMDAL)
+ # Check for HEIMDAL
+ find_package(PkgConfig)
+ if (PKG_CONFIG_FOUND)
+ pkg_check_modules(_GSSAPI heimdal-gssapi)
+ endif (PKG_CONFIG_FOUND)
+
+ if (_GSSAPI_FOUND)
+ set(GSSAPI_FLAVOR_HEIMDAL TRUE)
+ else()
+ find_path(_GSSAPI_ROKEN
+ NAMES
+ roken.h
+ PATHS
+ ${GSSAPI_ROOT_DIR}/include
+ ${_GSSAPI_INCLUDEDIR})
+ if (_GSSAPI_ROKEN)
+ set(GSSAPI_FLAVOR_HEIMDAL TRUE)
+ endif()
+ endif ()
+ endif()
+endif (UNIX)
+
+find_path(GSSAPI_INCLUDE_DIR
+ NAMES
+ gssapi.h
+ gssapi/gssapi.h
+ PATHS
+ ${GSSAPI_ROOT_DIR}/include
+ ${_GSSAPI_INCLUDEDIR}
+)
+
+if (GSSAPI_FLAVOR_MIT)
+ find_library(GSSAPI_LIBRARY
+ NAMES
+ gssapi_krb5
+ PATHS
+ ${GSSAPI_ROOT_DIR}/lib
+ ${_GSSAPI_LIBDIR}
+ )
+
+ find_library(KRB5_LIBRARY
+ NAMES
+ krb5
+ PATHS
+ ${GSSAPI_ROOT_DIR}/lib
+ ${_GSSAPI_LIBDIR}
+ )
+
+ find_library(K5CRYPTO_LIBRARY
+ NAMES
+ k5crypto
+ PATHS
+ ${GSSAPI_ROOT_DIR}/lib
+ ${_GSSAPI_LIBDIR}
+ )
+
+ find_library(COM_ERR_LIBRARY
+ NAMES
+ com_err
+ PATHS
+ ${GSSAPI_ROOT_DIR}/lib
+ ${_GSSAPI_LIBDIR}
+ )
+
+ if (GSSAPI_LIBRARY)
+ set(GSSAPI_LIBRARIES
+ ${GSSAPI_LIBRARIES}
+ ${GSSAPI_LIBRARY}
+ )
+ endif (GSSAPI_LIBRARY)
+
+ if (KRB5_LIBRARY)
+ set(GSSAPI_LIBRARIES
+ ${GSSAPI_LIBRARIES}
+ ${KRB5_LIBRARY}
+ )
+ endif (KRB5_LIBRARY)
+
+ if (K5CRYPTO_LIBRARY)
+ set(GSSAPI_LIBRARIES
+ ${GSSAPI_LIBRARIES}
+ ${K5CRYPTO_LIBRARY}
+ )
+ endif (K5CRYPTO_LIBRARY)
+
+ if (COM_ERR_LIBRARY)
+ set(GSSAPI_LIBRARIES
+ ${GSSAPI_LIBRARIES}
+ ${COM_ERR_LIBRARY}
+ )
+ endif (COM_ERR_LIBRARY)
+endif (GSSAPI_FLAVOR_MIT)
+
+if (GSSAPI_FLAVOR_HEIMDAL)
+ find_library(GSSAPI_LIBRARY
+ NAMES
+ gssapi
+ PATHS
+ ${GSSAPI_ROOT_DIR}/lib
+ ${_GSSAPI_LIBDIR}
+ )
+
+ find_library(KRB5_LIBRARY
+ NAMES
+ krb5
+ PATHS
+ ${GSSAPI_ROOT_DIR}/lib
+ ${_GSSAPI_LIBDIR}
+ )
+
+ find_library(HCRYPTO_LIBRARY
+ NAMES
+ hcrypto
+ PATHS
+ ${GSSAPI_ROOT_DIR}/lib
+ ${_GSSAPI_LIBDIR}
+ )
+
+ find_library(COM_ERR_LIBRARY
+ NAMES
+ com_err
+ PATHS
+ ${GSSAPI_ROOT_DIR}/lib
+ ${_GSSAPI_LIBDIR}
+ )
+
+ find_library(HEIMNTLM_LIBRARY
+ NAMES
+ heimntlm
+ PATHS
+ ${GSSAPI_ROOT_DIR}/lib
+ ${_GSSAPI_LIBDIR}
+ )
+
+ find_library(HX509_LIBRARY
+ NAMES
+ hx509
+ PATHS
+ ${GSSAPI_ROOT_DIR}/lib
+ ${_GSSAPI_LIBDIR}
+ )
+
+ find_library(ASN1_LIBRARY
+ NAMES
+ asn1
+ PATHS
+ ${GSSAPI_ROOT_DIR}/lib
+ ${_GSSAPI_LIBDIR}
+ )
+
+ find_library(WIND_LIBRARY
+ NAMES
+ wind
+ PATHS
+ ${GSSAPI_ROOT_DIR}/lib
+ ${_GSSAPI_LIBDIR}
+ )
+
+ find_library(ROKEN_LIBRARY
+ NAMES
+ roken
+ PATHS
+ ${GSSAPI_ROOT_DIR}/lib
+ ${_GSSAPI_LIBDIR}
+ )
+
+ if (GSSAPI_LIBRARY)
+ set(GSSAPI_LIBRARIES
+ ${GSSAPI_LIBRARIES}
+ ${GSSAPI_LIBRARY}
+ )
+ endif (GSSAPI_LIBRARY)
+
+ if (KRB5_LIBRARY)
+ set(GSSAPI_LIBRARIES
+ ${GSSAPI_LIBRARIES}
+ ${KRB5_LIBRARY}
+ )
+ endif (KRB5_LIBRARY)
+
+ if (HCRYPTO_LIBRARY)
+ set(GSSAPI_LIBRARIES
+ ${GSSAPI_LIBRARIES}
+ ${HCRYPTO_LIBRARY}
+ )
+ endif (HCRYPTO_LIBRARY)
+
+ if (COM_ERR_LIBRARY)
+ set(GSSAPI_LIBRARIES
+ ${GSSAPI_LIBRARIES}
+ ${COM_ERR_LIBRARY}
+ )
+ endif (COM_ERR_LIBRARY)
+
+ if (HEIMNTLM_LIBRARY)
+ set(GSSAPI_LIBRARIES
+ ${GSSAPI_LIBRARIES}
+ ${HEIMNTLM_LIBRARY}
+ )
+ endif (HEIMNTLM_LIBRARY)
+
+ if (HX509_LIBRARY)
+ set(GSSAPI_LIBRARIES
+ ${GSSAPI_LIBRARIES}
+ ${HX509_LIBRARY}
+ )
+ endif (HX509_LIBRARY)
+
+ if (ASN1_LIBRARY)
+ set(GSSAPI_LIBRARIES
+ ${GSSAPI_LIBRARIES}
+ ${ASN1_LIBRARY}
+ )
+ endif (ASN1_LIBRARY)
+
+ if (WIND_LIBRARY)
+ set(GSSAPI_LIBRARIES
+ ${GSSAPI_LIBRARIES}
+ ${WIND_LIBRARY}
+ )
+ endif (WIND_LIBRARY)
+
+ if (ROKEN_LIBRARY)
+ set(GSSAPI_LIBRARIES
+ ${GSSAPI_LIBRARIES}
+ ${WIND_LIBRARY}
+ )
+ endif (ROKEN_LIBRARY)
+endif (GSSAPI_FLAVOR_HEIMDAL)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(GSSAPI DEFAULT_MSG GSSAPI_LIBRARIES GSSAPI_INCLUDE_DIR)
+
+if (GSSAPI_INCLUDE_DIRS AND GSSAPI_LIBRARIES)
+ set(GSSAPI_FOUND TRUE)
+endif (GSSAPI_INCLUDE_DIRS AND GSSAPI_LIBRARIES)
+
+# show the GSSAPI_INCLUDE_DIRS and GSSAPI_LIBRARIES variables only in the advanced view
+mark_as_advanced(GSSAPI_INCLUDE_DIRS GSSAPI_LIBRARIES)
diff --git a/libssh b/libssh
new file mode 160000
+Subproject e8322817a9e5aaef0698d779ddd467a209a85d8
diff --git a/patch/libssh-0.10.4.patch b/patch/libssh-0.10.4.patch
new file mode 100644
index 0000000..bd6dc0e
--- /dev/null
+++ b/patch/libssh-0.10.4.patch
@@ -0,0 +1,157 @@
+diff --git a/DefineOptions.cmake b/DefineOptions.cmake
+index 068db988..7f42c2f3 100644
+--- a/DefineOptions.cmake
++++ b/DefineOptions.cmake
+@@ -25,6 +25,7 @@ option(WITH_GEX "Enable DH Group exchange mechanisms" ON)
+ option(WITH_INSECURE_NONE "Enable insecure none cipher and MAC algorithms (not suitable for production!)" OFF)
+ option(FUZZ_TESTING "Build with fuzzer for the server and client (automatically enables none cipher!)" OFF)
+ option(PICKY_DEVELOPER "Build with picky developer flags" OFF)
++option(WITH_STATIC_LIB "Build static library" ON)
+
+ if (WITH_ZLIB)
+ set(WITH_LIBZ ON)
+@@ -60,3 +61,7 @@ endif (NOT GLOBAL_CLIENT_CONFIG)
+ if (FUZZ_TESTING)
+ set(WITH_INSECURE_NONE ON)
+ endif (FUZZ_TESTING)
++
++if (WITH_STATIC_LIB)
++ set(BUILD_STATIC_LIB ON)
++endif()
+diff --git a/include/libssh/sftp.h b/include/libssh/sftp.h
+index c855df8a..1fd1710a 100644
+--- a/include/libssh/sftp.h
++++ b/include/libssh/sftp.h
+@@ -565,6 +565,9 @@ LIBSSH_API int sftp_async_read(sftp_file file, void *data, uint32_t len, uint32_
+ */
+ LIBSSH_API ssize_t sftp_write(sftp_file file, const void *buf, size_t count);
+
++LIBSSH_API int sftp_async_write(sftp_file file, const void *buf, size_t count, uint32_t* id);
++LIBSSH_API int sftp_async_write_end(sftp_file file, uint32_t id, int blocking);
++
+ /**
+ * @brief Seek to a specific location in a file.
+ *
+diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
+index c090fef7..e2f86309 100644
+--- a/src/CMakeLists.txt
++++ b/src/CMakeLists.txt
+@@ -435,6 +435,11 @@ if (BUILD_STATIC_LIB)
+ if (WIN32)
+ target_compile_definitions(ssh-static PUBLIC "LIBSSH_STATIC")
+ endif (WIN32)
++
++ install(TARGETS ssh-static
++ EXPORT libssh-config
++ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
++ COMPONENT libraries)
+ endif (BUILD_STATIC_LIB)
+
+ message(STATUS "Threads_FOUND=${Threads_FOUND}")
+diff --git a/src/sftp.c b/src/sftp.c
+index e01012a8..7b5dc249 100644
+--- a/src/sftp.c
++++ b/src/sftp.c
+@@ -2228,6 +2228,102 @@ ssize_t sftp_write(sftp_file file, const void *buf, size_t count) {
+ return -1; /* not reached */
+ }
+
++/*
++ * sftp_async_write and sftp_async_write_end are copied from
++ * https://github.com/limes-datentechnik-gmbh/libssh
++ */
++int sftp_async_write(sftp_file file, const void *buf, size_t count, uint32_t* id) {
++ sftp_session sftp = file->sftp;
++ ssh_buffer buffer;
++ int len;
++ int packetlen;
++ int rc;
++
++ buffer = ssh_buffer_new();
++ if (buffer == NULL) {
++ ssh_set_error_oom(sftp->session);
++ return -1;
++ }
++
++ *id = sftp_get_new_id(file->sftp);
++
++ rc = ssh_buffer_pack(buffer,
++ "dSqdP",
++ *id,
++ file->handle,
++ file->offset,
++ count, /* len of datastring */
++ (size_t)count, buf);
++ if (rc != SSH_OK){
++ ssh_set_error_oom(sftp->session);
++ ssh_buffer_free(buffer);
++ return SSH_ERROR;
++ }
++ packetlen=ssh_buffer_get_len(buffer)+5;
++ len = sftp_packet_write(file->sftp, SSH_FXP_WRITE, buffer);
++ ssh_buffer_free(buffer);
++ if (len < 0) {
++ return SSH_ERROR;
++ } else if (len != packetlen) {
++ ssh_set_error(sftp->session, SSH_FATAL,
++ "Could only send %d of %d bytes to remote host!", len, packetlen);
++ SSH_LOG(SSH_LOG_PACKET,
++ "Could not write as much data as expected");
++ return SSH_ERROR;
++ }
++
++ file->offset += count;
++
++ return SSH_OK;
++}
++
++int sftp_async_write_end(sftp_file file, uint32_t id, int blocking) {
++ sftp_session sftp = file->sftp;
++ sftp_message msg = NULL;
++ sftp_status_message status;
++
++ msg = sftp_dequeue(sftp, id);
++ while (msg == NULL) {
++ if (!blocking && ssh_channel_poll(sftp->channel, 0) == 0) {
++ /* we cannot block */
++ return SSH_AGAIN;
++ }
++ if (sftp_read_and_dispatch(sftp) < 0) {
++ /* something nasty has happened */
++ return SSH_ERROR;
++ }
++ msg = sftp_dequeue(sftp, id);
++ }
++
++ switch (msg->packet_type) {
++ case SSH_FXP_STATUS:
++ status = parse_status_msg(msg);
++ sftp_message_free(msg);
++ if (status == NULL) {
++ return SSH_ERROR;
++ }
++ sftp_set_error(sftp, status->status);
++ switch (status->status) {
++ case SSH_FX_OK:
++ status_msg_free(status);
++ return SSH_OK;
++ default:
++ break;
++ }
++ ssh_set_error(sftp->session, SSH_REQUEST_DENIED,
++ "SFTP server: %s", status->errormsg);
++ status_msg_free(status);
++ return SSH_ERROR;
++ default:
++ ssh_set_error(sftp->session, SSH_FATAL,
++ "Received message %d during write!", msg->packet_type);
++ sftp_message_free(msg);
++ return SSH_ERROR;
++ }
++
++ return SSH_ERROR; /* not reached */
++}
++
+ /* Seek to a specific location in a file. */
+ int sftp_seek(sftp_file file, uint32_t new_offset) {
+ if (file == NULL) {