mirror of
https://github.com/apache/nuttx-apps.git
synced 2026-08-01 20:29:00 +00:00
netutils/dropbear: add Dropbear SSH server port for NuttX
Integrated SSH daemon authenticating against FSUTILS_PASSWD, with an ECDSA P-256 host key and an NSH session over a PTY per connection. Built from the upstream Dropbear tarball (pinned commit) and patched for NuttX, using Dropbear's bundled libtomcrypt for all crypto. setsid() (apache/nuttx#19184) and link() now come from NuttX, not local stubs. Signed-off-by: Felipe Moura <moura.fmo@gmail.com>
This commit is contained in:
parent
e44c4f370f
commit
fee2ddbf54
24 changed files with 2449 additions and 1 deletions
|
|
@ -69,7 +69,7 @@ int passwd_append(FAR const char *username, FAR const char *password)
|
|||
{
|
||||
int errcode = errno;
|
||||
DEBUGASSERT(errcode > 0);
|
||||
return errcode;
|
||||
return -errcode;
|
||||
}
|
||||
|
||||
/* The format of the password file is:
|
||||
|
|
|
|||
6
netutils/dropbear/.gitignore
vendored
Normal file
6
netutils/dropbear/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
/dropbear
|
||||
/*.zip
|
||||
*.o
|
||||
.built
|
||||
.depend
|
||||
Make.dep
|
||||
185
netutils/dropbear/CMakeLists.txt
Normal file
185
netutils/dropbear/CMakeLists.txt
Normal file
|
|
@ -0,0 +1,185 @@
|
|||
# ##############################################################################
|
||||
# apps/netutils/dropbear/CMakeLists.txt
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more contributor
|
||||
# license agreements. See the NOTICE file distributed with this work for
|
||||
# additional information regarding copyright ownership. The ASF licenses this
|
||||
# file to you under the Apache License, Version 2.0 (the "License"); you may not
|
||||
# use this file except in compliance with the License. You may obtain a copy of
|
||||
# the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations under
|
||||
# the License.
|
||||
#
|
||||
# ##############################################################################
|
||||
|
||||
if(CONFIG_NETUTILS_DROPBEAR)
|
||||
|
||||
set(DROPBEAR_COMMIT "${CONFIG_NETUTILS_DROPBEAR_COMMIT}")
|
||||
string(REPLACE "\"" "" DROPBEAR_COMMIT "${DROPBEAR_COMMIT}")
|
||||
|
||||
set(DROPBEAR_ZIP "${DROPBEAR_COMMIT}.zip")
|
||||
set(DROPBEAR_URL "https://github.com/mkj/dropbear/archive")
|
||||
set(DROPBEAR_UNPACKNAME "dropbear")
|
||||
|
||||
if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${DROPBEAR_UNPACKNAME}")
|
||||
if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${DROPBEAR_ZIP}")
|
||||
message(STATUS "Downloading Dropbear: ${DROPBEAR_URL}/${DROPBEAR_ZIP}")
|
||||
file(DOWNLOAD "${DROPBEAR_URL}/${DROPBEAR_ZIP}"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/${DROPBEAR_ZIP}")
|
||||
endif()
|
||||
message(STATUS "Unpacking Dropbear: ${DROPBEAR_ZIP}")
|
||||
execute_process(
|
||||
COMMAND unzip -q -o "${DROPBEAR_ZIP}"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}"
|
||||
RESULT_VARIABLE result)
|
||||
if(result EQUAL 0)
|
||||
file(RENAME "${CMAKE_CURRENT_SOURCE_DIR}/dropbear-${DROPBEAR_COMMIT}"
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/${DROPBEAR_UNPACKNAME}")
|
||||
execute_process(
|
||||
COMMAND
|
||||
patch -s -N -l -p1 -d "${DROPBEAR_UNPACKNAME}" -i
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/patch/0001-guard-platform-declarations.patch"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
execute_process(
|
||||
COMMAND
|
||||
patch -s -N -l -p1 -d "${DROPBEAR_UNPACKNAME}" -i
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/patch/0002-use-nuttx-passwd-auth.patch"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
execute_process(
|
||||
COMMAND
|
||||
patch -s -N -l -p1 -d "${DROPBEAR_UNPACKNAME}" -i
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/patch/0003-allow-localoptions-to-override-tracking-malloc.patch"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
execute_process(
|
||||
COMMAND
|
||||
patch -s -N -l -p1 -d "${DROPBEAR_UNPACKNAME}" -i
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/patch/0004-use-nuttx-unused-macro.patch"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
message(STATUS "Generating default_options_guard.h")
|
||||
execute_process(
|
||||
COMMAND
|
||||
sh
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/${DROPBEAR_UNPACKNAME}/src/ifndef_wrapper.sh"
|
||||
INPUT_FILE
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/${DROPBEAR_UNPACKNAME}/src/default_options.h"
|
||||
OUTPUT_FILE
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/${DROPBEAR_UNPACKNAME}/src/default_options_guard.h"
|
||||
WORKING_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(PROGNAME "${CONFIG_NETUTILS_DROPBEAR_PROGNAME}")
|
||||
string(REPLACE "\"" "" PROGNAME "${PROGNAME}")
|
||||
|
||||
set(DROPBEAR_SRCS
|
||||
dropbear_nshsession.c
|
||||
port/nuttx_auth.c
|
||||
port/dropbear_utils.c
|
||||
dropbear/src/dbutil.c
|
||||
dropbear/src/buffer.c
|
||||
dropbear/src/dbhelpers.c
|
||||
dropbear/src/bignum.c
|
||||
dropbear/src/signkey.c
|
||||
dropbear/src/dbrandom.c
|
||||
dropbear/src/queue.c
|
||||
dropbear/src/atomicio.c
|
||||
dropbear/src/compat.c
|
||||
dropbear/src/fake-rfc2553.c
|
||||
dropbear/src/curve25519.c
|
||||
dropbear/src/chachapoly.c
|
||||
dropbear/src/ltc_prng.c
|
||||
dropbear/src/ecc.c
|
||||
dropbear/src/ecdsa.c
|
||||
dropbear/src/crypto_desc.c
|
||||
dropbear/src/dbmalloc.c
|
||||
dropbear/src/gensignkey.c
|
||||
dropbear/src/common-session.c
|
||||
dropbear/src/packet.c
|
||||
dropbear/src/common-algo.c
|
||||
dropbear/src/common-kex.c
|
||||
dropbear/src/common-channel.c
|
||||
dropbear/src/common-chansession.c
|
||||
dropbear/src/termcodes.c
|
||||
dropbear/src/tcp-accept.c
|
||||
dropbear/src/listener.c
|
||||
dropbear/src/process-packet.c
|
||||
dropbear/src/common-runopts.c
|
||||
dropbear/src/circbuffer.c
|
||||
dropbear/src/list.c
|
||||
dropbear/src/netio.c
|
||||
dropbear/src/gcm.c
|
||||
dropbear/src/kex-x25519.c
|
||||
dropbear/src/svr-kex.c
|
||||
dropbear/src/svr-auth.c
|
||||
dropbear/src/svr-authpasswd.c
|
||||
dropbear/src/svr-session.c
|
||||
dropbear/src/svr-service.c
|
||||
dropbear/src/svr-runopts.c
|
||||
dropbear/src/svr-tcpfwd.c
|
||||
dropbear/src/svr-forward.c
|
||||
dropbear/src/svr-streamfwd.c
|
||||
dropbear/src/svr-authpam.c)
|
||||
|
||||
file(GLOB LIBTOMMATH_SRCS CONFIGURE_DEPENDS
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/dropbear/libtommath/*.c")
|
||||
list(APPEND DROPBEAR_SRCS ${LIBTOMMATH_SRCS})
|
||||
|
||||
file(GLOB_RECURSE LIBTOMCRYPT_SRCS CONFIGURE_DEPENDS
|
||||
"${CMAKE_CURRENT_SOURCE_DIR}/dropbear/libtomcrypt/src/*.c")
|
||||
list(FILTER LIBTOMCRYPT_SRCS EXCLUDE REGEX ".*/prngs/sober128tab\\.c$")
|
||||
list(APPEND DROPBEAR_SRCS ${LIBTOMCRYPT_SRCS})
|
||||
|
||||
nuttx_add_application(
|
||||
NAME
|
||||
${PROGNAME}
|
||||
SRCS
|
||||
${DROPBEAR_SRCS}
|
||||
dropbear_main.c
|
||||
STACKSIZE
|
||||
${CONFIG_NETUTILS_DROPBEAR_STACKSIZE}
|
||||
PRIORITY
|
||||
${CONFIG_NETUTILS_DROPBEAR_PRIORITY}
|
||||
DEPENDS
|
||||
${DROPBEAR_UNPACKNAME})
|
||||
|
||||
target_include_directories(
|
||||
${PROGNAME}
|
||||
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/port
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/dropbear
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/dropbear/src
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/dropbear/libtomcrypt/src/headers
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/dropbear/libtommath
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/../../nshlib)
|
||||
|
||||
if(CONFIG_NETUTILS_DROPBEAR_COMPRESSION)
|
||||
target_include_directories(
|
||||
${PROGNAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../system/zlib/zlib)
|
||||
endif()
|
||||
|
||||
target_compile_definitions(
|
||||
${PROGNAME} PRIVATE LOCALOPTIONS_H_EXISTS=1 DROPBEAR_NUTTX=1
|
||||
DROPBEAR_NUTTX_PASSWD=1)
|
||||
|
||||
set_source_files_properties(
|
||||
dropbear_nshsession.c
|
||||
PROPERTIES COMPILE_DEFINITIONS
|
||||
"Channel=dropbear_channel;ChanType=dropbear_chantype")
|
||||
|
||||
# LTC_SOURCE must be set only for libtomcrypt sources.
|
||||
set_source_files_properties(${LIBTOMCRYPT_SRCS} PROPERTIES COMPILE_DEFINITIONS
|
||||
LTC_SOURCE=1)
|
||||
|
||||
target_compile_options(${PROGNAME} PRIVATE -Wno-pointer-sign -Wno-format)
|
||||
|
||||
target_sources(apps PRIVATE ${DROPBEAR_SRCS})
|
||||
|
||||
endif()
|
||||
120
netutils/dropbear/Kconfig
Normal file
120
netutils/dropbear/Kconfig
Normal file
|
|
@ -0,0 +1,120 @@
|
|||
#
|
||||
# For a description of the syntax of this configuration file,
|
||||
# see the file kconfig-language.txt in the NuttX tools repository.
|
||||
#
|
||||
|
||||
menuconfig NETUTILS_DROPBEAR
|
||||
tristate "Dropbear SSH server"
|
||||
default n
|
||||
depends on NET && NET_TCP
|
||||
depends on !DISABLE_PSEUDOFS_OPERATIONS
|
||||
depends on !DISABLE_PTHREAD
|
||||
depends on SCHED_WAITPID
|
||||
depends on NSH_LIBRARY
|
||||
depends on FSUTILS_PASSWD
|
||||
depends on PSEUDOTERM
|
||||
depends on SERIAL
|
||||
depends on ARCH_HAVE_RNG
|
||||
depends on DEV_RANDOM
|
||||
depends on DEV_URANDOM
|
||||
depends on LIBC_NETDB
|
||||
depends on LIBC_GAISTRERROR
|
||||
select CRYPTO
|
||||
select CRYPTO_RANDOM_POOL
|
||||
---help---
|
||||
Enable a minimal Dropbear SSH server port for NuttX. This initial
|
||||
port is based on the ESP-IDF MCU test port and provides a single
|
||||
foreground SSH server process with SSH sessions backed by NSH.
|
||||
|
||||
if NETUTILS_DROPBEAR
|
||||
|
||||
config NETUTILS_DROPBEAR_STACKSIZE
|
||||
int "Dropbear main stack size"
|
||||
default 65536
|
||||
---help---
|
||||
Stack size for the Dropbear server built-in.
|
||||
This is architecture-specific, so adjust it according to your setup.
|
||||
|
||||
config NETUTILS_DROPBEAR_PRIORITY
|
||||
int "Dropbear main priority"
|
||||
default 100
|
||||
|
||||
config NETUTILS_DROPBEAR_SHELL_PRIORITY
|
||||
int "Dropbear NSH session priority"
|
||||
default 100
|
||||
|
||||
config NETUTILS_DROPBEAR_PROGNAME
|
||||
string "Dropbear program name"
|
||||
default "dropbear"
|
||||
---help---
|
||||
This is the name of the program that will be used when the NSH ELF
|
||||
program is installed.
|
||||
|
||||
config NETUTILS_DROPBEAR_LISTEN_RETRIES
|
||||
int "Dropbear listen retries"
|
||||
default 0
|
||||
---help---
|
||||
Number of times to retry listen setup when no listen socket could
|
||||
be opened. Zero means to retry forever.
|
||||
|
||||
config NETUTILS_DROPBEAR_LISTEN_RETRY_MAX
|
||||
int "Dropbear maximum listen retry interval"
|
||||
default 120
|
||||
range 1 3600
|
||||
---help---
|
||||
Maximum number of seconds to wait between listen setup retries.
|
||||
The retry delay starts at one second and doubles until it reaches
|
||||
this value.
|
||||
|
||||
config NETUTILS_DROPBEAR_SHELL_STACKSIZE
|
||||
int "Dropbear NSH session task stack size"
|
||||
default 8192
|
||||
|
||||
config NETUTILS_DROPBEAR_PORT
|
||||
int "Dropbear listen port"
|
||||
default 2222
|
||||
|
||||
config NETUTILS_DROPBEAR_HOSTKEY_PATH
|
||||
string "Dropbear ECDSA P-256 host key path"
|
||||
default "/etc/dropbear/dropbear_ecdsa_host_key"
|
||||
---help---
|
||||
Path to the persistent ECDSA P-256 host key used by the Dropbear
|
||||
server. The file is stored in Dropbear's native host key format.
|
||||
|
||||
config NETUTILS_DROPBEAR_GENERATE_HOSTKEY
|
||||
bool "Generate host key if missing"
|
||||
default y
|
||||
---help---
|
||||
Pass -R so Dropbear generates an ECDSA P-256 host key on demand and
|
||||
persists it at NETUTILS_DROPBEAR_HOSTKEY_PATH when it does not exist.
|
||||
Product builds can disable this and provision the host key
|
||||
externally (loaded with -r).
|
||||
|
||||
config NETUTILS_DROPBEAR_COMPRESSION
|
||||
bool "Enable SSH compression (zlib)"
|
||||
default n
|
||||
depends on LIB_ZLIB
|
||||
---help---
|
||||
Enable zlib compression for SSH sessions. Requires the zlib
|
||||
library (LIB_ZLIB). When disabled, Dropbear is built with
|
||||
DISABLE_ZLIB and negotiates no compression.
|
||||
|
||||
WARNING: each session allocates a zlib deflate state of about
|
||||
256 KiB (DROPBEAR_ZLIB_WINDOW_BITS=15, DROPBEAR_ZLIB_MEM_LEVEL=8),
|
||||
and the state is allocated even for the delayed zlib@openssh.com
|
||||
method, right after key exchange.
|
||||
|
||||
config NETUTILS_DROPBEAR_SYSLOG
|
||||
bool "Log via syslog"
|
||||
default n
|
||||
---help---
|
||||
Route Dropbear log messages through syslog(). When disabled,
|
||||
Dropbear is built with DISABLE_SYSLOG.
|
||||
|
||||
config NETUTILS_DROPBEAR_COMMIT
|
||||
string "Dropbear upstream commit"
|
||||
default "54ef47adf8c99b422be6a8f694f2866e62f88b9e"
|
||||
---help---
|
||||
Upstream Dropbear (mkj/dropbear) commit to download and build.
|
||||
|
||||
endif
|
||||
25
netutils/dropbear/Make.defs
Normal file
25
netutils/dropbear/Make.defs
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
############################################################################
|
||||
# apps/netutils/dropbear/Make.defs
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership. The
|
||||
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance with the
|
||||
# License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
ifneq ($(CONFIG_NETUTILS_DROPBEAR),)
|
||||
CONFIGURED_APPS += $(APPDIR)/netutils/dropbear
|
||||
endif
|
||||
157
netutils/dropbear/Makefile
Normal file
157
netutils/dropbear/Makefile
Normal file
|
|
@ -0,0 +1,157 @@
|
|||
############################################################################
|
||||
# apps/netutils/dropbear/Makefile
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership. The
|
||||
# ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance with the
|
||||
# License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
include $(APPDIR)/Make.defs
|
||||
|
||||
ifneq ($(CONFIG_NETUTILS_DROPBEAR),)
|
||||
|
||||
DROPBEAR_COMMIT = $(patsubst "%",%,$(strip $(CONFIG_NETUTILS_DROPBEAR_COMMIT)))
|
||||
DROPBEAR_ZIP = $(DROPBEAR_COMMIT).zip
|
||||
DROPBEAR_UNPACKNAME = dropbear
|
||||
DROPBEAR_URL = https://github.com/mkj/dropbear/archive
|
||||
UNPACK ?= unzip -q -o
|
||||
ifeq ($(CONFIG_HOST_MACOS),y)
|
||||
PATCH ?= gpatch
|
||||
else
|
||||
PATCH ?= patch
|
||||
endif
|
||||
|
||||
MODULE = $(CONFIG_NETUTILS_DROPBEAR)
|
||||
PROGNAME = $(CONFIG_NETUTILS_DROPBEAR_PROGNAME)
|
||||
PRIORITY = $(CONFIG_NETUTILS_DROPBEAR_PRIORITY)
|
||||
STACKSIZE = $(CONFIG_NETUTILS_DROPBEAR_STACKSIZE)
|
||||
|
||||
CFLAGS += ${INCDIR_PREFIX}"$(APPDIR)$(DELIM)netutils$(DELIM)dropbear"
|
||||
CFLAGS += ${INCDIR_PREFIX}"$(APPDIR)$(DELIM)netutils$(DELIM)dropbear$(DELIM)port"
|
||||
CFLAGS += ${INCDIR_PREFIX}"$(APPDIR)$(DELIM)netutils$(DELIM)dropbear$(DELIM)dropbear"
|
||||
CFLAGS += ${INCDIR_PREFIX}"$(APPDIR)$(DELIM)netutils$(DELIM)dropbear$(DELIM)dropbear$(DELIM)src"
|
||||
CFLAGS += ${INCDIR_PREFIX}"$(APPDIR)$(DELIM)netutils$(DELIM)dropbear$(DELIM)dropbear$(DELIM)libtomcrypt$(DELIM)src$(DELIM)headers"
|
||||
CFLAGS += ${INCDIR_PREFIX}"$(APPDIR)$(DELIM)netutils$(DELIM)dropbear$(DELIM)dropbear$(DELIM)libtommath"
|
||||
CFLAGS += ${INCDIR_PREFIX}"$(APPDIR)$(DELIM)nshlib"
|
||||
|
||||
ifneq ($(CONFIG_NETUTILS_DROPBEAR_COMPRESSION),)
|
||||
CFLAGS += ${INCDIR_PREFIX}"$(APPDIR)$(DELIM)system$(DELIM)zlib$(DELIM)zlib"
|
||||
endif
|
||||
|
||||
CFLAGS += ${DEFINE_PREFIX}LOCALOPTIONS_H_EXISTS=1
|
||||
CFLAGS += ${DEFINE_PREFIX}DROPBEAR_NUTTX=1
|
||||
CFLAGS += ${DEFINE_PREFIX}DROPBEAR_NUTTX_PASSWD=1
|
||||
CFLAGS += -Wno-pointer-sign -Wno-format
|
||||
|
||||
dropbear_nshsession.c_CFLAGS += ${DEFINE_PREFIX}Channel=dropbear_channel
|
||||
dropbear_nshsession.c_CFLAGS += ${DEFINE_PREFIX}ChanType=dropbear_chantype
|
||||
|
||||
CSRCS = dropbear_nshsession.c
|
||||
CSRCS += port/nuttx_auth.c
|
||||
CSRCS += port/dropbear_utils.c
|
||||
|
||||
CSRCS += \
|
||||
dropbear/src/dbutil.c \
|
||||
dropbear/src/buffer.c \
|
||||
dropbear/src/dbhelpers.c \
|
||||
dropbear/src/bignum.c \
|
||||
dropbear/src/signkey.c \
|
||||
dropbear/src/dbrandom.c \
|
||||
dropbear/src/queue.c \
|
||||
dropbear/src/atomicio.c \
|
||||
dropbear/src/compat.c \
|
||||
dropbear/src/fake-rfc2553.c \
|
||||
dropbear/src/curve25519.c \
|
||||
dropbear/src/chachapoly.c \
|
||||
dropbear/src/ltc_prng.c \
|
||||
dropbear/src/ecc.c \
|
||||
dropbear/src/ecdsa.c \
|
||||
dropbear/src/crypto_desc.c \
|
||||
dropbear/src/dbmalloc.c \
|
||||
dropbear/src/gensignkey.c \
|
||||
dropbear/src/common-session.c \
|
||||
dropbear/src/packet.c \
|
||||
dropbear/src/common-algo.c \
|
||||
dropbear/src/common-kex.c \
|
||||
dropbear/src/common-channel.c \
|
||||
dropbear/src/common-chansession.c \
|
||||
dropbear/src/termcodes.c \
|
||||
dropbear/src/tcp-accept.c \
|
||||
dropbear/src/listener.c \
|
||||
dropbear/src/process-packet.c \
|
||||
dropbear/src/common-runopts.c \
|
||||
dropbear/src/circbuffer.c \
|
||||
dropbear/src/list.c \
|
||||
dropbear/src/netio.c \
|
||||
dropbear/src/gcm.c \
|
||||
dropbear/src/kex-x25519.c \
|
||||
dropbear/src/svr-kex.c \
|
||||
dropbear/src/svr-auth.c \
|
||||
dropbear/src/svr-authpasswd.c \
|
||||
dropbear/src/svr-session.c \
|
||||
dropbear/src/svr-service.c \
|
||||
dropbear/src/svr-runopts.c \
|
||||
dropbear/src/svr-tcpfwd.c \
|
||||
dropbear/src/svr-forward.c \
|
||||
dropbear/src/svr-streamfwd.c \
|
||||
dropbear/src/svr-authpam.c
|
||||
|
||||
TOMMATH_SRCS = $(shell if [ -d "$(DROPBEAR_UNPACKNAME)/libtommath" ]; then find "$(DROPBEAR_UNPACKNAME)/libtommath" -name "*.c"; fi)
|
||||
TOMCRYPT_SRCS = $(shell if [ -d "$(DROPBEAR_UNPACKNAME)/libtomcrypt/src" ]; then find "$(DROPBEAR_UNPACKNAME)/libtomcrypt/src" -name "*.c" ! -name "sober128tab.c"; fi)
|
||||
|
||||
CSRCS += $(TOMMATH_SRCS)
|
||||
CSRCS += $(TOMCRYPT_SRCS)
|
||||
|
||||
# Match the ESP-IDF port behavior: LTC_SOURCE is only for libtomcrypt sources.
|
||||
$(foreach src,$(TOMCRYPT_SRCS),$(eval $(src)_CFLAGS += ${DEFINE_PREFIX}LTC_SOURCE=1))
|
||||
|
||||
MAINSRC = dropbear_main.c
|
||||
|
||||
$(DROPBEAR_ZIP):
|
||||
@echo "Downloading: $(DROPBEAR_ZIP)"
|
||||
$(Q) curl -L -o $(DROPBEAR_ZIP) $(DROPBEAR_URL)/$(DROPBEAR_ZIP)
|
||||
|
||||
$(DROPBEAR_UNPACKNAME): $(DROPBEAR_ZIP)
|
||||
@echo "Unpacking: $(DROPBEAR_ZIP) -> $(DROPBEAR_UNPACKNAME)"
|
||||
$(Q) $(UNPACK) $(DROPBEAR_ZIP)
|
||||
$(Q) rm -rf $(DROPBEAR_UNPACKNAME)
|
||||
$(Q) mv dropbear-$(DROPBEAR_COMMIT) $(DROPBEAR_UNPACKNAME)
|
||||
@echo "Patching $(DROPBEAR_UNPACKNAME)"
|
||||
$(Q) $(PATCH) -s -N -l -p1 -d $(DROPBEAR_UNPACKNAME) -i $(APPDIR)$(DELIM)netutils$(DELIM)dropbear$(DELIM)patch$(DELIM)0001-guard-platform-declarations.patch; true
|
||||
$(Q) $(PATCH) -s -N -l -p1 -d $(DROPBEAR_UNPACKNAME) -i $(APPDIR)$(DELIM)netutils$(DELIM)dropbear$(DELIM)patch$(DELIM)0002-use-nuttx-passwd-auth.patch; true
|
||||
$(Q) $(PATCH) -s -N -l -p1 -d $(DROPBEAR_UNPACKNAME) -i $(APPDIR)$(DELIM)netutils$(DELIM)dropbear$(DELIM)patch$(DELIM)0003-allow-localoptions-to-override-tracking-malloc.patch; true
|
||||
$(Q) $(PATCH) -s -N -l -p1 -d $(DROPBEAR_UNPACKNAME) -i $(APPDIR)$(DELIM)netutils$(DELIM)dropbear$(DELIM)patch$(DELIM)0004-use-nuttx-unused-macro.patch; true
|
||||
@echo "Generating default_options_guard.h"
|
||||
$(Q) sh $(DROPBEAR_UNPACKNAME)$(DELIM)src$(DELIM)ifndef_wrapper.sh \
|
||||
< $(DROPBEAR_UNPACKNAME)$(DELIM)src$(DELIM)default_options.h \
|
||||
> $(DROPBEAR_UNPACKNAME)$(DELIM)src$(DELIM)default_options_guard.h
|
||||
$(Q) touch $(DROPBEAR_UNPACKNAME)
|
||||
|
||||
ifeq ($(wildcard $(DROPBEAR_UNPACKNAME)/.git),)
|
||||
context:: $(DROPBEAR_UNPACKNAME)
|
||||
|
||||
clean::
|
||||
$(call DELFILE, port$(DELIM)*.o)
|
||||
|
||||
distclean::
|
||||
$(call DELDIR, $(DROPBEAR_UNPACKNAME))
|
||||
$(call DELFILE, $(DROPBEAR_ZIP))
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
include $(APPDIR)/Application.mk
|
||||
329
netutils/dropbear/dropbear_main.c
Normal file
329
netutils/dropbear/dropbear_main.c
Normal file
|
|
@ -0,0 +1,329 @@
|
|||
/****************************************************************************
|
||||
* apps/netutils/dropbear/dropbear_main.c
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/socket.h>
|
||||
#include <setjmp.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "includes.h"
|
||||
#include "algo.h"
|
||||
#include "crypto_desc.h"
|
||||
#define dropbear_main dropbear_multi_entry
|
||||
#include "dbutil.h"
|
||||
#undef dropbear_main
|
||||
#include "dbrandom.h"
|
||||
#include "netio.h"
|
||||
#include "runopts.h"
|
||||
#include "session.h"
|
||||
#include "signkey.h"
|
||||
#include "gensignkey.h"
|
||||
#include "ssh.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define DROPBEAR_PORT_STRING_HELPER(n) #n
|
||||
#define DROPBEAR_PORT_STRING(n) DROPBEAR_PORT_STRING_HELPER(n)
|
||||
|
||||
/****************************************************************************
|
||||
* Private Types
|
||||
****************************************************************************/
|
||||
|
||||
typedef void (*dropbear_exit_handler_t)(int exitcode, FAR const char *format,
|
||||
va_list param) ATTRIB_NORETURN;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static jmp_buf g_session_exit_jmp;
|
||||
static int g_session_exitcode;
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static void dropbear_session_exit(int exitcode, FAR const char *format,
|
||||
va_list param) noreturn_function;
|
||||
static void dropbear_session_exit(int exitcode, FAR const char *format,
|
||||
va_list param)
|
||||
{
|
||||
char exitmsg[150];
|
||||
char fullmsg[300];
|
||||
char fromaddr[60];
|
||||
int signal_pipe[2];
|
||||
|
||||
vsnprintf(exitmsg, sizeof(exitmsg), format, param);
|
||||
|
||||
fromaddr[0] = '\0';
|
||||
|
||||
if (svr_ses.addrstring != NULL)
|
||||
{
|
||||
snprintf(fromaddr, sizeof(fromaddr), " from <%s>", svr_ses.addrstring);
|
||||
}
|
||||
|
||||
if (!ses.init_done)
|
||||
{
|
||||
snprintf(fullmsg, sizeof(fullmsg), "Early exit%s: %s", fromaddr,
|
||||
exitmsg);
|
||||
}
|
||||
else if (ses.authstate.authdone)
|
||||
{
|
||||
snprintf(fullmsg, sizeof(fullmsg), "Exit (%s)%s: %s",
|
||||
ses.authstate.pw_name, fromaddr, exitmsg);
|
||||
}
|
||||
else if (ses.authstate.pw_name != NULL)
|
||||
{
|
||||
snprintf(fullmsg, sizeof(fullmsg),
|
||||
"Exit before auth%s: (user '%s', %u fails): %s",
|
||||
fromaddr, ses.authstate.pw_name, ses.authstate.failcount,
|
||||
exitmsg);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(fullmsg, sizeof(fullmsg), "Exit before auth%s: %s", fromaddr,
|
||||
exitmsg);
|
||||
}
|
||||
|
||||
dropbear_log(LOG_INFO, "%s", fullmsg);
|
||||
|
||||
signal_pipe[0] = ses.signal_pipe[0];
|
||||
signal_pipe[1] = ses.signal_pipe[1];
|
||||
session_cleanup();
|
||||
|
||||
if (signal_pipe[0] > STDERR_FILENO)
|
||||
{
|
||||
m_close(signal_pipe[0]);
|
||||
}
|
||||
|
||||
if (signal_pipe[1] > STDERR_FILENO && signal_pipe[1] != signal_pipe[0])
|
||||
{
|
||||
m_close(signal_pipe[1]);
|
||||
}
|
||||
|
||||
memset(&ses, 0, sizeof(ses));
|
||||
memset(&svr_ses, 0, sizeof(svr_ses));
|
||||
|
||||
g_session_exitcode = exitcode;
|
||||
longjmp(g_session_exit_jmp, 1);
|
||||
|
||||
while (1)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
static void dropbear_setup(FAR const char *port)
|
||||
{
|
||||
/* Load the host key with -r so it lives in the persistent (epoch 0)
|
||||
* allocation rather than being created lazily inside a per-session malloc
|
||||
* epoch (-R), which would free it when the first session ends and leave a
|
||||
* dangling svr_opts.hostkey for the next connection.
|
||||
*/
|
||||
|
||||
FAR char *argv[] =
|
||||
{
|
||||
"dropbear",
|
||||
"-F",
|
||||
"-p",
|
||||
(FAR char *)port,
|
||||
"-r",
|
||||
CONFIG_NETUTILS_DROPBEAR_HOSTKEY_PATH,
|
||||
NULL
|
||||
};
|
||||
|
||||
_dropbear_exit = svr_dropbear_exit;
|
||||
_dropbear_log = svr_dropbear_log;
|
||||
|
||||
disallow_core();
|
||||
svr_getopts(6, argv);
|
||||
seedrandom();
|
||||
crypto_init();
|
||||
|
||||
#ifdef CONFIG_NETUTILS_DROPBEAR_GENERATE_HOSTKEY
|
||||
/* Generate the ECDSA host key now if it is missing. signkey_generate()
|
||||
* with skip_exist=1 silently succeeds when the file already exists.
|
||||
*/
|
||||
|
||||
if (signkey_generate(DROPBEAR_SIGNKEY_ECDSA_NISTP256, 0,
|
||||
CONFIG_NETUTILS_DROPBEAR_HOSTKEY_PATH, 1)
|
||||
== DROPBEAR_FAILURE)
|
||||
{
|
||||
dropbear_exit("failed to generate host key");
|
||||
}
|
||||
#endif
|
||||
|
||||
load_all_hostkeys();
|
||||
|
||||
if (dropbear_auth_initialize() < 0)
|
||||
{
|
||||
dropbear_exit("failed to initialize password auth");
|
||||
}
|
||||
}
|
||||
|
||||
static void dropbear_run_session(int childsock)
|
||||
{
|
||||
dropbear_exit_handler_t saved_exit;
|
||||
|
||||
saved_exit = _dropbear_exit;
|
||||
_dropbear_exit = dropbear_session_exit;
|
||||
|
||||
m_malloc_set_epoch(1);
|
||||
|
||||
if (setjmp(g_session_exit_jmp) == 0)
|
||||
{
|
||||
svr_session(childsock, -1);
|
||||
}
|
||||
|
||||
m_malloc_free_epoch(1, 1);
|
||||
m_malloc_set_epoch(0);
|
||||
|
||||
_dropbear_exit = saved_exit;
|
||||
|
||||
if (g_session_exitcode != EXIT_SUCCESS)
|
||||
{
|
||||
dropbear_log(LOG_WARNING, "session exited with status %d",
|
||||
g_session_exitcode);
|
||||
}
|
||||
}
|
||||
|
||||
static size_t dropbear_listen_sockets(FAR int *socks, size_t sockcount,
|
||||
FAR int *maxfd)
|
||||
{
|
||||
FAR char *errstring = NULL;
|
||||
size_t sockpos = 0;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < svr_opts.portcount; i++)
|
||||
{
|
||||
int nsock;
|
||||
unsigned int n;
|
||||
|
||||
nsock = dropbear_listen(svr_opts.addresses[i], svr_opts.ports[i],
|
||||
&socks[sockpos], sockcount - sockpos,
|
||||
&errstring, maxfd, svr_opts.interface);
|
||||
|
||||
if (nsock < 0)
|
||||
{
|
||||
dropbear_log(LOG_WARNING, "failed listening on '%s': %s",
|
||||
svr_opts.ports[i],
|
||||
errstring != NULL ? errstring : "unknown error");
|
||||
m_free(errstring);
|
||||
errstring = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (n = 0; n < (unsigned int)nsock; n++)
|
||||
{
|
||||
set_sock_priority(socks[sockpos + n], DROPBEAR_PRIO_LOWDELAY);
|
||||
}
|
||||
|
||||
sockpos += (size_t)nsock;
|
||||
}
|
||||
|
||||
return sockpos;
|
||||
}
|
||||
|
||||
static size_t dropbear_wait_listen_sockets(FAR int *socks, size_t sockcount,
|
||||
FAR int *maxfd)
|
||||
{
|
||||
int retries = 0;
|
||||
int retry_delay = 1;
|
||||
|
||||
while (1)
|
||||
{
|
||||
size_t count;
|
||||
|
||||
*maxfd = -1;
|
||||
count = dropbear_listen_sockets(socks, sockcount, maxfd);
|
||||
|
||||
if (count > 0)
|
||||
{
|
||||
return count;
|
||||
}
|
||||
|
||||
#if CONFIG_NETUTILS_DROPBEAR_LISTEN_RETRIES > 0
|
||||
if (retries++ >= CONFIG_NETUTILS_DROPBEAR_LISTEN_RETRIES)
|
||||
{
|
||||
dropbear_exit("no listening ports available");
|
||||
}
|
||||
#else
|
||||
retries++;
|
||||
#endif
|
||||
|
||||
dropbear_log(LOG_WARNING, "Retry %d in %d seconds...", retries,
|
||||
retry_delay);
|
||||
sleep(retry_delay);
|
||||
|
||||
retry_delay *= 2;
|
||||
|
||||
if (retry_delay > CONFIG_NETUTILS_DROPBEAR_LISTEN_RETRY_MAX)
|
||||
{
|
||||
retry_delay = CONFIG_NETUTILS_DROPBEAR_LISTEN_RETRY_MAX;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
int main(int argc, FAR char *argv[])
|
||||
{
|
||||
FAR const char *port = DROPBEAR_PORT_STRING(CONFIG_NETUTILS_DROPBEAR_PORT);
|
||||
int listensocks[MAX_LISTEN_ADDR];
|
||||
int maxfd = -1;
|
||||
|
||||
if (argc > 1)
|
||||
{
|
||||
port = argv[1];
|
||||
}
|
||||
|
||||
dropbear_setup(port);
|
||||
|
||||
dropbear_wait_listen_sockets(listensocks, MAX_LISTEN_ADDR, &maxfd);
|
||||
|
||||
printf("dropbear: listening on port %s\n", port);
|
||||
|
||||
while (1)
|
||||
{
|
||||
struct sockaddr_storage remoteaddr;
|
||||
socklen_t remoteaddrlen = sizeof(remoteaddr);
|
||||
FAR char *remote_host = NULL;
|
||||
FAR char *remote_port = NULL;
|
||||
int childsock;
|
||||
|
||||
childsock = accept(listensocks[0], (FAR struct sockaddr *)&remoteaddr,
|
||||
&remoteaddrlen);
|
||||
|
||||
if (childsock < 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
getaddrstring(&remoteaddr, &remote_host, &remote_port, 0);
|
||||
dropbear_log(LOG_INFO, "connection from %s:%s",
|
||||
remote_host != NULL ? remote_host : "?",
|
||||
remote_port != NULL ? remote_port : "?");
|
||||
m_free(remote_host);
|
||||
m_free(remote_port);
|
||||
|
||||
seedrandom();
|
||||
dropbear_run_session(childsock);
|
||||
close(childsock);
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
633
netutils/dropbear/dropbear_nshsession.c
Normal file
633
netutils/dropbear/dropbear_nshsession.c
Normal file
|
|
@ -0,0 +1,633 @@
|
|||
/****************************************************************************
|
||||
* apps/netutils/dropbear/dropbear_nshsession.c
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include "includes.h"
|
||||
#include "channel.h"
|
||||
#include "chansession.h"
|
||||
#include "dbutil.h"
|
||||
#include "session.h"
|
||||
|
||||
#include "nsh.h"
|
||||
#include "nsh_console.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <pty.h>
|
||||
#include <pthread.h>
|
||||
#include <sched.h>
|
||||
#include <signal.h>
|
||||
#include <spawn.h>
|
||||
#include <stdbool.h>
|
||||
#include <string.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/wait.h>
|
||||
#include <termios.h>
|
||||
#include <unistd.h>
|
||||
|
||||
struct dropbear_nshsession_s
|
||||
{
|
||||
int pty_readfd;
|
||||
int pty_writefd;
|
||||
pid_t nsh_pid;
|
||||
volatile bool done;
|
||||
pthread_t waiter;
|
||||
bool waiter_started;
|
||||
bool have_winsize;
|
||||
struct winsize win;
|
||||
};
|
||||
|
||||
struct dropbear_signal_name_s
|
||||
{
|
||||
FAR const char *name;
|
||||
int signo;
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static const struct dropbear_signal_name_s g_dropbear_signals[] =
|
||||
{
|
||||
{ "ABRT", SIGABRT },
|
||||
{ "ALRM", SIGALRM },
|
||||
{ "FPE", SIGFPE },
|
||||
{ "HUP", SIGHUP },
|
||||
{ "ILL", SIGILL },
|
||||
{ "INT", SIGINT },
|
||||
{ "KILL", SIGKILL },
|
||||
{ "PIPE", SIGPIPE },
|
||||
{ "QUIT", SIGQUIT },
|
||||
{ "SEGV", SIGSEGV },
|
||||
{ "TERM", SIGTERM },
|
||||
{ "USR1", SIGUSR1 },
|
||||
{ "USR2", SIGUSR2 },
|
||||
};
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static int dropbear_nsh_main(int argc, FAR char *argv[])
|
||||
{
|
||||
FAR struct console_stdio_s *pstate;
|
||||
FAR char *nsh_argv[] =
|
||||
{
|
||||
"nsh",
|
||||
NULL
|
||||
};
|
||||
|
||||
int ret;
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
pstate = nsh_newconsole(true);
|
||||
if (pstate == NULL)
|
||||
{
|
||||
dropbear_log(LOG_WARNING, "failed to create NSH console");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
ret = nsh_session(pstate, NSH_LOGIN_NONE, 1, nsh_argv);
|
||||
dropbear_log(LOG_INFO, "NSH session exited: %d", ret);
|
||||
|
||||
nsh_exit(&pstate->cn_vtbl, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static FAR void *dropbear_nsh_waiter(FAR void *arg)
|
||||
{
|
||||
FAR struct dropbear_nshsession_s *sess = arg;
|
||||
unsigned char ch = 0;
|
||||
int status;
|
||||
int ret;
|
||||
|
||||
ret = waitpid(sess->nsh_pid, &status, 0);
|
||||
if (ret < 0)
|
||||
{
|
||||
dropbear_log(LOG_WARNING, "NSH session wait failed: %s",
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
sess->nsh_pid = -1;
|
||||
sess->done = true;
|
||||
|
||||
/* Match Dropbear's SIGCHLD wakeup path. The session loop checks channel
|
||||
* close conditions when this pipe becomes readable.
|
||||
*/
|
||||
|
||||
if (ses.signal_pipe[1] >= 0)
|
||||
{
|
||||
write(ses.signal_pipe[1], &ch, sizeof(ch));
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int dropbear_newchansess(FAR struct dropbear_channel *channel)
|
||||
{
|
||||
FAR struct dropbear_nshsession_s *sess;
|
||||
|
||||
sess = m_malloc(sizeof(*sess));
|
||||
memset(sess, 0, sizeof(*sess));
|
||||
sess->pty_readfd = -1;
|
||||
sess->pty_writefd = -1;
|
||||
sess->nsh_pid = -1;
|
||||
|
||||
channel->typedata = sess;
|
||||
channel->prio = DROPBEAR_PRIO_LOWDELAY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int dropbear_sesscheckclose(FAR struct dropbear_channel *channel)
|
||||
{
|
||||
FAR struct dropbear_nshsession_s *sess = channel->typedata;
|
||||
|
||||
return sess != NULL && sess->done;
|
||||
}
|
||||
|
||||
static int dropbear_setup_spawn_attrs(FAR posix_spawnattr_t *attr,
|
||||
FAR const char **errmsg)
|
||||
{
|
||||
struct sched_param param;
|
||||
int rc;
|
||||
|
||||
param.sched_priority = CONFIG_NETUTILS_DROPBEAR_SHELL_PRIORITY;
|
||||
*errmsg = "spawn priority setup";
|
||||
rc = posix_spawnattr_setschedparam(attr, ¶m);
|
||||
if (rc != 0)
|
||||
{
|
||||
return rc;
|
||||
}
|
||||
|
||||
*errmsg = "spawn stack setup";
|
||||
rc = posix_spawnattr_setstacksize(
|
||||
attr, CONFIG_NETUTILS_DROPBEAR_SHELL_STACKSIZE);
|
||||
if (rc != 0)
|
||||
{
|
||||
return rc;
|
||||
}
|
||||
|
||||
*errmsg = "spawn flags setup";
|
||||
return posix_spawnattr_setflags(attr, POSIX_SPAWN_SETSCHEDPARAM);
|
||||
}
|
||||
|
||||
static int
|
||||
dropbear_setup_spawn_stdio(FAR posix_spawn_file_actions_t *actions,
|
||||
int slavefd)
|
||||
{
|
||||
static const int stdio_fds[] =
|
||||
{
|
||||
STDIN_FILENO,
|
||||
STDOUT_FILENO,
|
||||
STDERR_FILENO
|
||||
};
|
||||
|
||||
int i;
|
||||
int rc;
|
||||
|
||||
for (i = 0; i < nitems(stdio_fds); i++)
|
||||
{
|
||||
rc = posix_spawn_file_actions_adddup2(actions, slavefd, stdio_fds[i]);
|
||||
if (rc != 0)
|
||||
{
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
dropbear_setup_spawn_close(FAR posix_spawn_file_actions_t *actions,
|
||||
int fd)
|
||||
{
|
||||
if (fd <= STDERR_FILENO)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
return posix_spawn_file_actions_addclose(actions, fd);
|
||||
}
|
||||
|
||||
static int dropbear_start_nsh(FAR struct dropbear_channel *channel,
|
||||
FAR struct dropbear_nshsession_s *sess)
|
||||
{
|
||||
posix_spawn_file_actions_t actions;
|
||||
posix_spawnattr_t attr;
|
||||
FAR const char *errmsg;
|
||||
FAR char * const argv[] =
|
||||
{
|
||||
"nsh",
|
||||
NULL
|
||||
};
|
||||
|
||||
int masterfd;
|
||||
int slavefd;
|
||||
int writefd;
|
||||
int rc;
|
||||
|
||||
if (sess->nsh_pid >= 0)
|
||||
{
|
||||
dropbear_log(LOG_WARNING, "NSH session already running");
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
|
||||
rc = openpty(&masterfd, &slavefd, NULL, NULL,
|
||||
sess->have_winsize ? &sess->win : NULL);
|
||||
if (rc < 0)
|
||||
{
|
||||
dropbear_log(LOG_WARNING, "openpty failed: %s", strerror(errno));
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
|
||||
writefd = dup(masterfd);
|
||||
if (writefd < 0)
|
||||
{
|
||||
dropbear_log(LOG_WARNING, "pty dup failed: %s", strerror(errno));
|
||||
close(masterfd);
|
||||
close(slavefd);
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
|
||||
rc = posix_spawn_file_actions_init(&actions);
|
||||
if (rc != 0)
|
||||
{
|
||||
dropbear_log(LOG_WARNING, "spawn actions init failed: %s",
|
||||
strerror(rc));
|
||||
close(masterfd);
|
||||
close(writefd);
|
||||
close(slavefd);
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
|
||||
rc = posix_spawnattr_init(&attr);
|
||||
if (rc != 0)
|
||||
{
|
||||
dropbear_log(LOG_WARNING, "spawn attr init failed: %s", strerror(rc));
|
||||
goto err_with_actions;
|
||||
}
|
||||
|
||||
rc = dropbear_setup_spawn_attrs(&attr, &errmsg);
|
||||
if (rc != 0)
|
||||
{
|
||||
dropbear_log(LOG_WARNING, "%s failed: %s", errmsg, strerror(rc));
|
||||
goto err_with_attr;
|
||||
}
|
||||
|
||||
rc = dropbear_setup_spawn_stdio(&actions, slavefd);
|
||||
if (rc != 0)
|
||||
{
|
||||
dropbear_log(LOG_WARNING, "spawn stdio setup failed: %s",
|
||||
strerror(rc));
|
||||
goto err_with_attr;
|
||||
}
|
||||
|
||||
rc = dropbear_setup_spawn_close(&actions, masterfd);
|
||||
if (rc != 0)
|
||||
{
|
||||
dropbear_log(LOG_WARNING, "spawn master close setup failed: %s",
|
||||
strerror(rc));
|
||||
goto err_with_attr;
|
||||
}
|
||||
|
||||
rc = dropbear_setup_spawn_close(&actions, writefd);
|
||||
if (rc != 0)
|
||||
{
|
||||
dropbear_log(LOG_WARNING, "spawn write close setup failed: %s",
|
||||
strerror(rc));
|
||||
goto err_with_attr;
|
||||
}
|
||||
|
||||
rc = dropbear_setup_spawn_close(&actions, slavefd);
|
||||
if (rc != 0)
|
||||
{
|
||||
dropbear_log(LOG_WARNING, "spawn slave close setup failed: %s",
|
||||
strerror(rc));
|
||||
goto err_with_attr;
|
||||
}
|
||||
|
||||
sess->nsh_pid = task_spawn("dropbear nsh", dropbear_nsh_main, &actions,
|
||||
&attr, argv, NULL);
|
||||
if (sess->nsh_pid < 0)
|
||||
{
|
||||
dropbear_log(LOG_WARNING, "failed to create NSH task: %s",
|
||||
strerror(-sess->nsh_pid));
|
||||
goto err_with_attr;
|
||||
}
|
||||
|
||||
close(slavefd);
|
||||
slavefd = -1;
|
||||
|
||||
rc = pthread_create(&sess->waiter, NULL, dropbear_nsh_waiter, sess);
|
||||
if (rc != 0)
|
||||
{
|
||||
dropbear_log(LOG_WARNING, "failed to create NSH waiter: %s",
|
||||
strerror(rc));
|
||||
close(masterfd);
|
||||
close(writefd);
|
||||
masterfd = -1;
|
||||
writefd = -1;
|
||||
kill(sess->nsh_pid, SIGTERM);
|
||||
waitpid(sess->nsh_pid, NULL, 0);
|
||||
sess->nsh_pid = -1;
|
||||
goto err_with_attr;
|
||||
}
|
||||
|
||||
sess->waiter_started = true;
|
||||
sess->pty_readfd = masterfd;
|
||||
sess->pty_writefd = writefd;
|
||||
|
||||
channel->readfd = masterfd;
|
||||
channel->writefd = writefd;
|
||||
channel->bidir_fd = 0;
|
||||
|
||||
setnonblocking(channel->readfd);
|
||||
setnonblocking(channel->writefd);
|
||||
ses.maxfd = MAX(ses.maxfd, channel->readfd);
|
||||
ses.maxfd = MAX(ses.maxfd, channel->writefd);
|
||||
|
||||
posix_spawnattr_destroy(&attr);
|
||||
posix_spawn_file_actions_destroy(&actions);
|
||||
|
||||
dropbear_log(LOG_INFO, "NSH PTY session started");
|
||||
return DROPBEAR_SUCCESS;
|
||||
|
||||
err_with_attr:
|
||||
posix_spawnattr_destroy(&attr);
|
||||
|
||||
err_with_actions:
|
||||
posix_spawn_file_actions_destroy(&actions);
|
||||
|
||||
if (masterfd >= 0)
|
||||
{
|
||||
close(masterfd);
|
||||
}
|
||||
|
||||
if (writefd >= 0)
|
||||
{
|
||||
close(writefd);
|
||||
}
|
||||
|
||||
if (slavefd >= 0)
|
||||
{
|
||||
close(slavefd);
|
||||
}
|
||||
|
||||
sess->nsh_pid = -1;
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
|
||||
static void dropbear_parse_winsize(FAR struct dropbear_nshsession_s *sess)
|
||||
{
|
||||
unsigned int cols = buf_getint(ses.payload);
|
||||
unsigned int rows = buf_getint(ses.payload);
|
||||
unsigned int width = buf_getint(ses.payload);
|
||||
unsigned int height = buf_getint(ses.payload);
|
||||
|
||||
sess->win.ws_col = cols;
|
||||
sess->win.ws_row = rows;
|
||||
sess->win.ws_xpixel = width;
|
||||
sess->win.ws_ypixel = height;
|
||||
sess->have_winsize = true;
|
||||
|
||||
if (sess->pty_readfd >= 0)
|
||||
{
|
||||
ioctl(sess->pty_readfd, TIOCSWINSZ, (unsigned long)&sess->win);
|
||||
}
|
||||
}
|
||||
|
||||
static int dropbear_handle_pty_req(FAR struct dropbear_nshsession_s *sess)
|
||||
{
|
||||
unsigned int len;
|
||||
FAR char *term;
|
||||
FAR char *modes;
|
||||
|
||||
term = buf_getstring(ses.payload, &len);
|
||||
dropbear_parse_winsize(sess);
|
||||
modes = buf_getstring(ses.payload, &len);
|
||||
|
||||
m_free(term);
|
||||
m_free(modes);
|
||||
return DROPBEAR_SUCCESS;
|
||||
}
|
||||
|
||||
static int dropbear_signal_from_name(FAR const char *name)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < nitems(g_dropbear_signals); i++)
|
||||
{
|
||||
if (strcmp(name, g_dropbear_signals[i].name) == 0)
|
||||
{
|
||||
return g_dropbear_signals[i].signo;
|
||||
}
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int dropbear_write_terminal_signal(
|
||||
FAR struct dropbear_nshsession_s *sess,
|
||||
int signo)
|
||||
{
|
||||
#ifdef CONFIG_TTY_SIGINT
|
||||
unsigned char ch;
|
||||
ssize_t nwritten;
|
||||
|
||||
if (signo == SIGINT && sess->pty_writefd >= 0)
|
||||
{
|
||||
ch = CONFIG_TTY_SIGINT_CHAR;
|
||||
nwritten = write(sess->pty_writefd, &ch, sizeof(ch));
|
||||
if (nwritten == sizeof(ch))
|
||||
{
|
||||
return DROPBEAR_SUCCESS;
|
||||
}
|
||||
|
||||
dropbear_log(LOG_WARNING, "SSH terminal INT failed: %s",
|
||||
strerror(errno));
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
#endif
|
||||
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
|
||||
static int dropbear_handle_signal(FAR struct dropbear_nshsession_s *sess)
|
||||
{
|
||||
unsigned int len;
|
||||
FAR char *name;
|
||||
int signo;
|
||||
int ret;
|
||||
|
||||
name = buf_getstring(ses.payload, &len);
|
||||
signo = dropbear_signal_from_name(name);
|
||||
if (signo < 0)
|
||||
{
|
||||
dropbear_log(LOG_WARNING, "unsupported SSH signal '%s'", name);
|
||||
m_free(name);
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
|
||||
ret = dropbear_write_terminal_signal(sess, signo);
|
||||
if (ret == DROPBEAR_SUCCESS)
|
||||
{
|
||||
dropbear_log(LOG_INFO, "SSH signal '%s' sent to PTY", name);
|
||||
m_free(name);
|
||||
return DROPBEAR_SUCCESS;
|
||||
}
|
||||
|
||||
if (sess->nsh_pid <= 0)
|
||||
{
|
||||
dropbear_log(LOG_WARNING, "SSH signal '%s' has no NSH session", name);
|
||||
m_free(name);
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
|
||||
ret = kill(sess->nsh_pid, signo);
|
||||
if (ret < 0)
|
||||
{
|
||||
dropbear_log(LOG_WARNING, "SSH signal '%s' failed: %s",
|
||||
name, strerror(errno));
|
||||
m_free(name);
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
|
||||
dropbear_log(LOG_INFO, "SSH signal '%s' sent to NSH session", name);
|
||||
m_free(name);
|
||||
return DROPBEAR_SUCCESS;
|
||||
}
|
||||
|
||||
static void dropbear_chansessionrequest(FAR struct dropbear_channel *channel)
|
||||
{
|
||||
unsigned int typelen;
|
||||
FAR char *type = buf_getstring(ses.payload, &typelen);
|
||||
unsigned char wantreply = buf_getbool(ses.payload);
|
||||
FAR struct dropbear_nshsession_s *sess = channel->typedata;
|
||||
int ret = DROPBEAR_FAILURE;
|
||||
|
||||
TRACE(("dropbear_chansessionrequest: type='%s'", type))
|
||||
|
||||
if (strcmp(type, "pty-req") == 0)
|
||||
{
|
||||
ret = dropbear_handle_pty_req(sess);
|
||||
}
|
||||
else if (strcmp(type, "shell") == 0)
|
||||
{
|
||||
ret = dropbear_start_nsh(channel, sess);
|
||||
}
|
||||
else if (strcmp(type, "exec") == 0)
|
||||
{
|
||||
dropbear_log(LOG_WARNING, "SSH exec requests are not supported");
|
||||
}
|
||||
else if (strcmp(type, "window-change") == 0)
|
||||
{
|
||||
dropbear_parse_winsize(sess);
|
||||
ret = DROPBEAR_SUCCESS;
|
||||
}
|
||||
else if (strcmp(type, "signal") == 0)
|
||||
{
|
||||
ret = dropbear_handle_signal(sess);
|
||||
}
|
||||
else if (strcmp(type, "break") == 0)
|
||||
{
|
||||
ret = DROPBEAR_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
TRACE(("dropbear_chansessionrequest: unhandled type '%s'", type))
|
||||
}
|
||||
|
||||
if (wantreply)
|
||||
{
|
||||
if (ret == DROPBEAR_SUCCESS)
|
||||
{
|
||||
send_msg_channel_success(channel);
|
||||
}
|
||||
else
|
||||
{
|
||||
send_msg_channel_failure(channel);
|
||||
}
|
||||
}
|
||||
|
||||
m_free(type);
|
||||
}
|
||||
|
||||
static void
|
||||
dropbear_closechansess(FAR const struct dropbear_channel *channel)
|
||||
{
|
||||
FAR struct dropbear_nshsession_s *sess = channel->typedata;
|
||||
|
||||
if (sess != NULL)
|
||||
{
|
||||
sess->done = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dropbear_cleanupchansess(FAR const struct dropbear_channel *channel)
|
||||
{
|
||||
FAR struct dropbear_nshsession_s *sess = channel->typedata;
|
||||
|
||||
if (sess == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
sess->done = true;
|
||||
|
||||
if (sess->nsh_pid > 0)
|
||||
{
|
||||
kill(sess->nsh_pid, SIGTERM);
|
||||
}
|
||||
|
||||
if (sess->waiter_started)
|
||||
{
|
||||
pthread_join(sess->waiter, NULL);
|
||||
sess->waiter_started = false;
|
||||
}
|
||||
|
||||
m_free(sess);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/* Chansession lifecycle hooks invoked from svr-session.c. Upstream
|
||||
* svr-chansession.c uses these to set up and reap the global childpids[] /
|
||||
* SIGCHLD machinery; the NSH bridge tracks each session's child through its
|
||||
* own waiter thread (dropbear_nsh_waiter), so both are no-ops here.
|
||||
*/
|
||||
|
||||
void svr_chansessinitialise(void)
|
||||
{
|
||||
}
|
||||
|
||||
void svr_chansess_checksignal(void)
|
||||
{
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Data
|
||||
****************************************************************************/
|
||||
|
||||
const struct dropbear_chantype svrchansess =
|
||||
{
|
||||
"session",
|
||||
dropbear_newchansess,
|
||||
dropbear_sesscheckclose,
|
||||
dropbear_chansessionrequest,
|
||||
dropbear_closechansess,
|
||||
dropbear_cleanupchansess,
|
||||
};
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
--- a/src/dbutil.c
|
||||
+++ b/src/dbutil.c
|
||||
@@ -66,6 +66,10 @@
|
||||
#include "session.h"
|
||||
#include "atomicio.h"
|
||||
|
||||
+#ifdef DROPBEAR_NUTTX
|
||||
+int execv(const char *path, char * const argv[]);
|
||||
+#endif
|
||||
+
|
||||
#define MAX_FMT 100
|
||||
|
||||
static void generic_dropbear_exit(int exitcode, const char* format,
|
||||
--- a/src/signkey.h
|
||||
+++ b/src/signkey.h
|
||||
@@ -150,9 +150,9 @@
|
||||
void buf_put_sign(buffer* buf, sign_key *key, enum signature_type sigtype, const buffer *data_buf);
|
||||
#if DROPBEAR_SIGNKEY_VERIFY
|
||||
int buf_verify(buffer * buf, sign_key *key, enum signature_type expect_sigtype, const buffer *data_buf);
|
||||
int sk_buf_verify(buffer * buf, sign_key *key, enum signature_type expect_sigtype, const buffer *data_buf, char* app, unsigned int applen);
|
||||
-char * sign_key_fingerprint(const unsigned char* keyblob, unsigned int keybloblen);
|
||||
#endif
|
||||
+char * sign_key_fingerprint(const unsigned char* keyblob, unsigned int keybloblen);
|
||||
int cmp_base64_key(const unsigned char* keyblob, unsigned int keybloblen,
|
||||
const unsigned char* algoname, unsigned int algolen,
|
||||
const buffer * line, char ** fingerprint);
|
||||
87
netutils/dropbear/patch/0002-use-nuttx-passwd-auth.patch
Normal file
87
netutils/dropbear/patch/0002-use-nuttx-passwd-auth.patch
Normal file
|
|
@ -0,0 +1,87 @@
|
|||
--- a/src/svr-authpasswd.c
|
||||
+++ b/src/svr-authpasswd.c
|
||||
@@ -33,6 +33,77 @@
|
||||
|
||||
#if DROPBEAR_SVR_PASSWORD_AUTH
|
||||
|
||||
+#if DROPBEAR_NUTTX_PASSWD
|
||||
+
|
||||
+/* Process a password auth request, sending success or failure messages as
|
||||
+ * appropriate */
|
||||
+void svr_auth_password(int valid_user) {
|
||||
+
|
||||
+ char * password = NULL;
|
||||
+ unsigned int passwordlen;
|
||||
+ unsigned int changepw;
|
||||
+ int auth_ok = 0;
|
||||
+
|
||||
+ /* check if client wants to change password */
|
||||
+ changepw = buf_getbool(ses.payload);
|
||||
+ if (changepw) {
|
||||
+ /* not implemented by this server */
|
||||
+ send_msg_userauth_failure(0, 1);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ password = buf_getstring(ses.payload, &passwordlen);
|
||||
+ if (valid_user && passwordlen <= DROPBEAR_MAX_PASSWORD_LEN &&
|
||||
+ strlen(password) == passwordlen) {
|
||||
+ auth_ok = dropbear_verify_password(ses.authstate.pw_name, password);
|
||||
+ }
|
||||
+ m_burn(password, passwordlen);
|
||||
+ m_free(password);
|
||||
+
|
||||
+ /* After we have got the payload contents we can exit if the username
|
||||
+ is invalid. Invalid users have already been logged. */
|
||||
+ if (!valid_user) {
|
||||
+ send_msg_userauth_failure(0, 1);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (passwordlen > DROPBEAR_MAX_PASSWORD_LEN) {
|
||||
+ dropbear_log(LOG_WARNING,
|
||||
+ "Too-long password attempt for '%s' from %s",
|
||||
+ ses.authstate.pw_name,
|
||||
+ svr_ses.addrstring);
|
||||
+ send_msg_userauth_failure(0, 1);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ if (auth_ok == DROPBEAR_SUCCESS) {
|
||||
+ if (svr_opts.multiauthmethod && (ses.authstate.authtypes & ~AUTH_TYPE_PASSWORD)) {
|
||||
+ /* successful password authentication, but extra auth required */
|
||||
+ dropbear_log(LOG_NOTICE,
|
||||
+ "Password auth succeeded for '%s' from %s, extra auth required",
|
||||
+ ses.authstate.pw_name,
|
||||
+ svr_ses.addrstring);
|
||||
+ ses.authstate.authtypes &= ~AUTH_TYPE_PASSWORD; /* password auth ok, delete the method flag */
|
||||
+ send_msg_userauth_failure(1, 0); /* Send partial success */
|
||||
+ } else {
|
||||
+ /* successful authentication */
|
||||
+ dropbear_log(LOG_NOTICE,
|
||||
+ "Password auth succeeded for '%s' from %s",
|
||||
+ ses.authstate.pw_name,
|
||||
+ svr_ses.addrstring);
|
||||
+ send_msg_userauth_success();
|
||||
+ }
|
||||
+ } else {
|
||||
+ dropbear_log(LOG_WARNING,
|
||||
+ "Bad password attempt for '%s' from %s",
|
||||
+ ses.authstate.pw_name,
|
||||
+ svr_ses.addrstring);
|
||||
+ send_msg_userauth_failure(0, 1);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+#else
|
||||
+
|
||||
/* not constant time when strings are differing lengths.
|
||||
string content isn't leaked, and crypt hashes are predictable length. */
|
||||
static int constant_time_strcmp(const char* a, const char* b) {
|
||||
@@ -131,4 +202,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
+#endif /* DROPBEAR_NUTTX_PASSWD */
|
||||
+
|
||||
#endif
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
--- a/src/sysoptions.h
|
||||
+++ b/src/sysoptions.h
|
||||
@@ -183,7 +183,9 @@ defined(__has_feature)
|
||||
#define LTC_ECC521
|
||||
#endif
|
||||
|
||||
-#define DROPBEAR_LTC_PRNG (DROPBEAR_ECC)
|
||||
+#ifndef DROPBEAR_LTC_PRNG
|
||||
+#define DROPBEAR_LTC_PRNG (DROPBEAR_ECC)
|
||||
+#endif
|
||||
|
||||
/* RSA can be vulnerable to timing attacks which use the time required for
|
||||
* signing to guess the private key. Blinding avoids this attack, though makes
|
||||
@@ -436,7 +438,9 @@ defined(__has_feature)
|
||||
#define DROPBEAR_CLIENT_TCP_FAST_OPEN 0
|
||||
#endif
|
||||
|
||||
-#define DROPBEAR_TRACKING_MALLOC (DROPBEAR_FUZZ)
|
||||
+#ifndef DROPBEAR_TRACKING_MALLOC
|
||||
+#define DROPBEAR_TRACKING_MALLOC (DROPBEAR_FUZZ)
|
||||
+#endif
|
||||
|
||||
/* Used to work around Memory Sanitizer false positives */
|
||||
#if defined(__has_feature)
|
||||
202
netutils/dropbear/patch/0004-use-nuttx-unused-macro.patch
Normal file
202
netutils/dropbear/patch/0004-use-nuttx-unused-macro.patch
Normal file
|
|
@ -0,0 +1,202 @@
|
|||
--- a/src/compat.c
|
||||
+++ b/src/compat.c
|
||||
@@ -89,6 +89,6 @@
|
||||
#ifndef HAVE_GETUSERSHELL
|
||||
static char **curshell, **shells, *strings;
|
||||
-static char **initshells();
|
||||
+static char **initshells(void);
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STRLCPY
|
||||
@@ -234,7 +234,7 @@
|
||||
curshell = initshells();
|
||||
}
|
||||
|
||||
-static char **initshells() {
|
||||
+static char **initshells(void) {
|
||||
static const char *okshells[] = { COMPAT_USER_SHELLS, NULL };
|
||||
register char **sp, *cp;
|
||||
register FILE *fp;
|
||||
--- a/src/common-algo.c
|
||||
+++ b/src/common-algo.c
|
||||
@@ -39,16 +39,25 @@
|
||||
/* This file (algo.c) organises the ciphers which can be used, and is used to
|
||||
* decide which ciphers/hashes/compression/signing to use during key exchange*/
|
||||
|
||||
-static int void_cipher(const unsigned char* in, unsigned char* out,
|
||||
- unsigned long len, void* UNUSED(cipher_state)) {
|
||||
+static int void_cipher(const unsigned char* in, unsigned char* out,
|
||||
+ unsigned long len, void* cipher_state) {
|
||||
+ UNUSED(cipher_state);
|
||||
+
|
||||
if (in != out) {
|
||||
memmove(out, in, len);
|
||||
}
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
-static int void_start(int UNUSED(cipher), const unsigned char* UNUSED(IV),
|
||||
- const unsigned char* UNUSED(key),
|
||||
- int UNUSED(keylen), int UNUSED(num_rounds), void* UNUSED(cipher_state)) {
|
||||
+static int void_start(int cipher, const unsigned char* IV,
|
||||
+ const unsigned char* key,
|
||||
+ int keylen, int num_rounds, void* cipher_state) {
|
||||
+ UNUSED(cipher);
|
||||
+ UNUSED(IV);
|
||||
+ UNUSED(key);
|
||||
+ UNUSED(keylen);
|
||||
+ UNUSED(num_rounds);
|
||||
+ UNUSED(cipher_state);
|
||||
+
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
--- a/src/common-channel.c
|
||||
+++ b/src/common-channel.c
|
||||
@@ -410,7 +410,9 @@
|
||||
|
||||
#ifndef HAVE_WRITEV
|
||||
static int writechannel_fallback(struct Channel* channel, int fd, circbuffer *cbuf,
|
||||
- const unsigned char *UNUSED(moredata), unsigned int *morelen) {
|
||||
+ const unsigned char *moredata, unsigned int *morelen) {
|
||||
+ UNUSED(moredata);
|
||||
+
|
||||
|
||||
unsigned char *circ_p1, *circ_p2;
|
||||
unsigned int circ_len1, circ_len2;
|
||||
--- a/src/dbutil.c
|
||||
+++ b/src/dbutil.c
|
||||
@@ -138,7 +138,9 @@
|
||||
}
|
||||
|
||||
-static void generic_dropbear_log(int UNUSED(priority), const char* format,
|
||||
+static void generic_dropbear_log(int priority, const char* format,
|
||||
va_list param) {
|
||||
+ UNUSED(priority);
|
||||
+
|
||||
|
||||
char printbuf[1024];
|
||||
|
||||
--- a/src/netio.c
|
||||
+++ b/src/netio.c
|
||||
@@ -47,7 +47,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
-static void cancel_callback(int result, int sock, void* UNUSED(data), const char* UNUSED(errstring)) {
|
||||
+static void cancel_callback(int result, int sock, void* data, const char* errstring) {
|
||||
+ UNUSED(data);
|
||||
+ UNUSED(errstring);
|
||||
+
|
||||
if (result == DROPBEAR_SUCCESS)
|
||||
{
|
||||
m_close(sock);
|
||||
--- a/src/ltc_prng.c
|
||||
+++ b/src/ltc_prng.c
|
||||
@@ -32,8 +32,10 @@
|
||||
@param prng [out] The PRNG state to initialize
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
-int dropbear_prng_start(prng_state* UNUSED(prng))
|
||||
+int dropbear_prng_start(prng_state* prng)
|
||||
{
|
||||
+ UNUSED(prng);
|
||||
+
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
@@ -44,8 +46,12 @@
|
||||
@param prng PRNG state to update
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
-int dropbear_prng_add_entropy(const unsigned char* UNUSED(in), unsigned long UNUSED(inlen), prng_state* UNUSED(prng))
|
||||
+int dropbear_prng_add_entropy(const unsigned char* in, unsigned long inlen, prng_state* prng)
|
||||
{
|
||||
+ UNUSED(in);
|
||||
+ UNUSED(inlen);
|
||||
+ UNUSED(prng);
|
||||
+
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
@@ -54,8 +60,10 @@
|
||||
@param prng The PRNG to make active
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
-int dropbear_prng_ready(prng_state* UNUSED(prng))
|
||||
+int dropbear_prng_ready(prng_state* prng)
|
||||
{
|
||||
+ UNUSED(prng);
|
||||
+
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
@@ -66,8 +74,10 @@
|
||||
@param prng The active PRNG to read from
|
||||
@return Number of octets read
|
||||
*/
|
||||
-unsigned long dropbear_prng_read(unsigned char* out, unsigned long outlen, prng_state* UNUSED(prng))
|
||||
+unsigned long dropbear_prng_read(unsigned char* out, unsigned long outlen, prng_state* prng)
|
||||
{
|
||||
+ UNUSED(prng);
|
||||
+
|
||||
LTC_ARGCHK(out != NULL);
|
||||
genrandom(out, outlen);
|
||||
return outlen;
|
||||
@@ -78,8 +88,10 @@
|
||||
@param prng The PRNG to terminate
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
-int dropbear_prng_done(prng_state* UNUSED(prng))
|
||||
+int dropbear_prng_done(prng_state* prng)
|
||||
{
|
||||
+ UNUSED(prng);
|
||||
+
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
@@ -90,8 +102,11 @@
|
||||
@param prng The PRNG to export
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
-int dropbear_prng_export(unsigned char* UNUSED(out), unsigned long* outlen, prng_state* UNUSED(prng))
|
||||
+int dropbear_prng_export(unsigned char* out, unsigned long* outlen, prng_state* prng)
|
||||
{
|
||||
+ UNUSED(out);
|
||||
+ UNUSED(prng);
|
||||
+
|
||||
LTC_ARGCHK(outlen != NULL);
|
||||
|
||||
*outlen = 0;
|
||||
@@ -105,8 +120,12 @@
|
||||
@param prng The PRNG to import
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
-int dropbear_prng_import(const unsigned char* UNUSED(in), unsigned long UNUSED(inlen), prng_state* UNUSED(prng))
|
||||
+int dropbear_prng_import(const unsigned char* in, unsigned long inlen, prng_state* prng)
|
||||
{
|
||||
+ UNUSED(in);
|
||||
+ UNUSED(inlen);
|
||||
+ UNUSED(prng);
|
||||
+
|
||||
return CRYPT_OK;
|
||||
}
|
||||
|
||||
--- a/src/chachapoly.c
|
||||
+++ b/src/chachapoly.c
|
||||
@@ -43,9 +43,13 @@
|
||||
const struct dropbear_cipher dropbear_chachapoly =
|
||||
{&dummy, CHACHA20_KEY_LEN*2, CHACHA20_BLOCKSIZE};
|
||||
|
||||
-static int dropbear_chachapoly_start(int UNUSED(cipher), const unsigned char* UNUSED(IV),
|
||||
+static int dropbear_chachapoly_start(int cipher, const unsigned char* IV,
|
||||
const unsigned char *key, int keylen,
|
||||
- int UNUSED(num_rounds), dropbear_chachapoly_state *state) {
|
||||
+ int num_rounds, dropbear_chachapoly_state *state) {
|
||||
+ UNUSED(cipher);
|
||||
+ UNUSED(IV);
|
||||
+ UNUSED(num_rounds);
|
||||
+
|
||||
int err;
|
||||
|
||||
TRACE2(("enter dropbear_chachapoly_start"))
|
||||
20
netutils/dropbear/port/config.h
Normal file
20
netutils/dropbear/port/config.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
/****************************************************************************
|
||||
* apps/netutils/dropbear/port/config.h
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __APPS_NETUTILS_DROPBEAR_PORT_CONFIG_H
|
||||
#define __APPS_NETUTILS_DROPBEAR_PORT_CONFIG_H
|
||||
|
||||
/* Dropbear looks for a file named config.h. Keep this wrapper name stable;
|
||||
* NuttX-specific autoconf replacements live in nuttx_config.h.
|
||||
*/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "nuttx_config.h"
|
||||
|
||||
#endif /* __APPS_NETUTILS_DROPBEAR_PORT_CONFIG_H */
|
||||
149
netutils/dropbear/port/dropbear_utils.c
Normal file
149
netutils/dropbear/port/dropbear_utils.c
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
/****************************************************************************
|
||||
* apps/netutils/dropbear/port/dropbear_utils.c
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "dropbear_utils.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static int dropbear_hex_value(char ch)
|
||||
{
|
||||
if (ch >= '0' && ch <= '9')
|
||||
{
|
||||
return ch - '0';
|
||||
}
|
||||
|
||||
if (ch >= 'a' && ch <= 'f')
|
||||
{
|
||||
return ch - 'a' + 10;
|
||||
}
|
||||
|
||||
if (ch >= 'A' && ch <= 'F')
|
||||
{
|
||||
return ch - 'A' + 10;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int dropbear_try_mkdir(FAR const char *path)
|
||||
{
|
||||
if (mkdir(path, 0700) < 0 && errno != EEXIST)
|
||||
{
|
||||
return -errno;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
void dropbear_hex_encode(FAR char *dst, FAR const uint8_t *src,
|
||||
size_t srclen)
|
||||
{
|
||||
static const char hex[] = "0123456789abcdef";
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < srclen; i++)
|
||||
{
|
||||
dst[i * 2] = hex[src[i] >> 4];
|
||||
dst[i * 2 + 1] = hex[src[i] & 0x0f];
|
||||
}
|
||||
|
||||
dst[srclen * 2] = '\0';
|
||||
}
|
||||
|
||||
int dropbear_hex_decode(FAR const char *src, size_t srclen,
|
||||
FAR uint8_t *dst, size_t dstlen)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
if (srclen != dstlen * 2)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < dstlen; i++)
|
||||
{
|
||||
int hi = dropbear_hex_value(src[i * 2]);
|
||||
int lo = dropbear_hex_value(src[i * 2 + 1]);
|
||||
|
||||
if (hi < 0 || lo < 0)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dst[i] = (uint8_t)((hi << 4) | lo);
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
int dropbear_try_prepare_parent(FAR const char *path)
|
||||
{
|
||||
char dir[PATH_MAX];
|
||||
struct stat st;
|
||||
FAR char *slash;
|
||||
FAR char *p;
|
||||
int ret;
|
||||
|
||||
if (strlcpy(dir, path, sizeof(dir)) >= sizeof(dir))
|
||||
{
|
||||
return -ENAMETOOLONG;
|
||||
}
|
||||
|
||||
slash = strrchr(dir, '/');
|
||||
if (slash == NULL || slash == dir)
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
|
||||
*slash = '\0';
|
||||
if (stat(dir, &st) == 0)
|
||||
{
|
||||
return OK;
|
||||
}
|
||||
|
||||
for (p = dir + 1; *p != '\0'; p++)
|
||||
{
|
||||
if (*p == '/')
|
||||
{
|
||||
*p = '\0';
|
||||
ret = dropbear_try_mkdir(dir);
|
||||
if (ret < 0)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
*p = '/';
|
||||
}
|
||||
}
|
||||
|
||||
return dropbear_try_mkdir(dir);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_SCHED_USER_IDENTITY
|
||||
int dropbear_getgroups(int size, gid_t list[])
|
||||
{
|
||||
(void)size;
|
||||
(void)list;
|
||||
set_errno(ENOSYS);
|
||||
return ERROR;
|
||||
}
|
||||
#endif
|
||||
31
netutils/dropbear/port/dropbear_utils.h
Normal file
31
netutils/dropbear/port/dropbear_utils.h
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
/****************************************************************************
|
||||
* apps/netutils/dropbear/port/dropbear_utils.h
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __APPS_NETUTILS_DROPBEAR_PORT_DROPBEAR_UTILS_H
|
||||
#define __APPS_NETUTILS_DROPBEAR_PORT_DROPBEAR_UTILS_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Public Function Prototypes
|
||||
****************************************************************************/
|
||||
|
||||
void dropbear_hex_encode(FAR char *dst, FAR const uint8_t *src,
|
||||
size_t srclen);
|
||||
|
||||
int dropbear_hex_decode(FAR const char *src, size_t srclen,
|
||||
FAR uint8_t *dst, size_t dstlen);
|
||||
|
||||
int dropbear_try_prepare_parent(FAR const char *path);
|
||||
|
||||
#endif /* __APPS_NETUTILS_DROPBEAR_PORT_DROPBEAR_UTILS_H */
|
||||
81
netutils/dropbear/port/localoptions.h
Normal file
81
netutils/dropbear/port/localoptions.h
Normal file
|
|
@ -0,0 +1,81 @@
|
|||
/****************************************************************************
|
||||
* apps/netutils/dropbear/port/localoptions.h
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __APPS_NETUTILS_DROPBEAR_PORT_LOCALOPTIONS_H
|
||||
#define __APPS_NETUTILS_DROPBEAR_PORT_LOCALOPTIONS_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define DROPBEAR_TRACKING_MALLOC 1
|
||||
|
||||
/* Persist the native Dropbear ECDSA host key at the configured path. */
|
||||
|
||||
#define ECDSA_PRIV_FILENAME CONFIG_NETUTILS_DROPBEAR_HOSTKEY_PATH
|
||||
|
||||
#define DROPBEAR_SVR_DROP_PRIVS 0
|
||||
|
||||
#ifdef CONFIG_SCHED_USER_IDENTITY
|
||||
# define DROPBEAR_SVR_MULTIUSER 1
|
||||
#else
|
||||
# define DROPBEAR_SVR_MULTIUSER 0
|
||||
#endif
|
||||
|
||||
#define DROPBEAR_SVR_PASSWORD_AUTH 1
|
||||
#define DROPBEAR_SVR_PUBKEY_AUTH 0
|
||||
#define DROPBEAR_SVR_PUBKEY_OPTIONS 0
|
||||
|
||||
#define DROPBEAR_REEXEC 0
|
||||
#define DROPBEAR_SMALL_CODE 1
|
||||
#define DROPBEAR_USER_ALGO_LIST 0
|
||||
|
||||
#define DROPBEAR_X11FWD 0
|
||||
#define DROPBEAR_SVR_AGENTFWD 0
|
||||
#define DROPBEAR_SVR_LOCALTCPFWD 0
|
||||
#define DROPBEAR_SVR_REMOTETCPFWD 0
|
||||
#define DROPBEAR_SVR_LOCALSTREAMFWD 0
|
||||
#define DROPBEAR_SVR_REMOTESTREAMFWD 0
|
||||
|
||||
#define DROPBEAR_DSS 0
|
||||
#define DROPBEAR_RSA 0
|
||||
#define DROPBEAR_ECDSA 1
|
||||
#define DROPBEAR_ED25519 0
|
||||
#define DROPBEAR_SK_KEYS 0
|
||||
#define DROPBEAR_ECC_256 1
|
||||
#define DROPBEAR_ECC_384 0
|
||||
#define DROPBEAR_ECC_521 0
|
||||
|
||||
#define DROPBEAR_AES128 1
|
||||
#define DROPBEAR_AES256 0
|
||||
#define DROPBEAR_CHACHA20POLY1305 1
|
||||
#define DROPBEAR_ENABLE_CBC_MODE 0
|
||||
#define DROPBEAR_ENABLE_GCM_MODE 0
|
||||
|
||||
#define DROPBEAR_SHA1_HMAC 0
|
||||
#define DROPBEAR_SHA2_256_HMAC 1
|
||||
#define DROPBEAR_SHA2_512_HMAC 0
|
||||
#define DROPBEAR_SHA1_96_HMAC 0
|
||||
|
||||
#define DROPBEAR_CURVE25519 1
|
||||
#define DROPBEAR_DH_GROUP14_SHA1 0
|
||||
#define DROPBEAR_DH_GROUP14_SHA256 0
|
||||
#define DROPBEAR_DH_GROUP16 0
|
||||
#define DROPBEAR_DH_GROUP1 0
|
||||
#define DROPBEAR_ECDH 0
|
||||
#define DROPBEAR_SNTRUP761 0
|
||||
#define DROPBEAR_MLKEM768 0
|
||||
|
||||
#define DROPBEAR_DEFAULT_CLI_AUTHKEY "/etc/dropbear/authorized_keys"
|
||||
#define DROPBEAR_SFTPSERVER 0
|
||||
|
||||
#endif /* __APPS_NETUTILS_DROPBEAR_PORT_LOCALOPTIONS_H */
|
||||
109
netutils/dropbear/port/nuttx_auth.c
Normal file
109
netutils/dropbear/port/nuttx_auth.c
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
/****************************************************************************
|
||||
* apps/netutils/dropbear/port/nuttx_auth.c
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
#include <pwd.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "fsutils/passwd.h"
|
||||
|
||||
#include "dbutil.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static struct passwd g_dropbear_pw;
|
||||
static char g_dropbear_name[64];
|
||||
static char g_dropbear_dir[] = "/";
|
||||
static char g_dropbear_shell[] = "/bin/sh";
|
||||
static char g_dropbear_password_marker[] = "x";
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
****************************************************************************/
|
||||
|
||||
static FAR struct passwd *dropbear_fill_pw(FAR const char *name, uid_t uid)
|
||||
{
|
||||
memset(&g_dropbear_pw, 0, sizeof(g_dropbear_pw));
|
||||
|
||||
snprintf(g_dropbear_name, sizeof(g_dropbear_name), "%s", name);
|
||||
|
||||
g_dropbear_pw.pw_uid = uid;
|
||||
g_dropbear_pw.pw_gid = 0;
|
||||
g_dropbear_pw.pw_name = g_dropbear_name;
|
||||
g_dropbear_pw.pw_passwd = g_dropbear_password_marker;
|
||||
g_dropbear_pw.pw_gecos = g_dropbear_name;
|
||||
g_dropbear_pw.pw_dir = g_dropbear_dir;
|
||||
g_dropbear_pw.pw_shell = g_dropbear_shell;
|
||||
|
||||
return &g_dropbear_pw;
|
||||
}
|
||||
|
||||
FAR struct passwd *dropbear_getpwuid(uid_t uid)
|
||||
{
|
||||
return dropbear_fill_pw("root", uid);
|
||||
}
|
||||
|
||||
FAR struct passwd *dropbear_getpwnam(FAR const char *name)
|
||||
{
|
||||
if (name == NULL || name[0] == '\0')
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return dropbear_fill_pw(name, 0);
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
uid_t dropbear_getuid(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uid_t dropbear_geteuid(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dropbear_auth_initialize(void)
|
||||
{
|
||||
dropbear_log(LOG_INFO, "using NuttX passwd auth at %s",
|
||||
CONFIG_FSUTILS_PASSWD_PATH);
|
||||
return OK;
|
||||
}
|
||||
|
||||
int dropbear_verify_password(FAR const char *username,
|
||||
FAR const char *password)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = passwd_verify(username, password);
|
||||
if (PASSWORD_VERIFY_MATCH(ret))
|
||||
{
|
||||
return DROPBEAR_SUCCESS;
|
||||
}
|
||||
|
||||
if (PASSWORD_VERIFY_ERROR(ret) && ret != -ENOENT)
|
||||
{
|
||||
dropbear_log(LOG_WARNING, "passwd_verify failed for '%s': %d",
|
||||
username, ret);
|
||||
}
|
||||
|
||||
return DROPBEAR_FAILURE;
|
||||
}
|
||||
142
netutils/dropbear/port/nuttx_config.h
Normal file
142
netutils/dropbear/port/nuttx_config.h
Normal file
|
|
@ -0,0 +1,142 @@
|
|||
/****************************************************************************
|
||||
* apps/netutils/dropbear/port/nuttx_config.h
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef __APPS_NETUTILS_DROPBEAR_PORT_NUTTX_CONFIG_H
|
||||
#define __APPS_NETUTILS_DROPBEAR_PORT_NUTTX_CONFIG_H
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
#include <grp.h>
|
||||
#include <pwd.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#define DROPBEAR_SERVER 1
|
||||
#define BUNDLED_LIBTOM 1
|
||||
#define DISABLE_LASTLOG 1
|
||||
#define DISABLE_PAM 1
|
||||
#define DISABLE_PUTUTLINE 1
|
||||
#define DISABLE_PUTUTXLINE 1
|
||||
#define DISABLE_UTMP 1
|
||||
#define DISABLE_UTMPX 1
|
||||
#define DISABLE_WTMP 1
|
||||
#define DISABLE_WTMPX 1
|
||||
|
||||
#ifndef CONFIG_NETUTILS_DROPBEAR_SYSLOG
|
||||
# define DISABLE_SYSLOG 1
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_NETUTILS_DROPBEAR_COMPRESSION
|
||||
# define DISABLE_ZLIB 1
|
||||
#endif
|
||||
|
||||
#define DROPBEAR_FUZZ 0
|
||||
#define DROPBEAR_PLUGIN 0
|
||||
|
||||
#define HAVE_BASENAME 1
|
||||
#define HAVE_CLOCK_GETTIME 1
|
||||
#define HAVE_CONST_GAI_STRERROR_PROTO 1
|
||||
#define HAVE_CRYPT 1
|
||||
#define HAVE_DECL_HTOLE64 1
|
||||
#define HAVE_ENDIAN_H 1
|
||||
#define HAVE_EXPLICIT_BZERO 1
|
||||
#define HAVE_FREEADDRINFO 1
|
||||
#define HAVE_GAI_STRERROR 1
|
||||
#define HAVE_GETADDRINFO 1
|
||||
#define HAVE_GETNAMEINFO 1
|
||||
#define HAVE_GETRANDOM 1
|
||||
#define HAVE_INTTYPES_H 1
|
||||
#define HAVE_LIBGEN_H 1
|
||||
#define HAVE_NETDB_H 1
|
||||
#define HAVE_NETINET_IN_H 1
|
||||
#define HAVE_NETINET_TCP_H 1
|
||||
#define HAVE_PATHS_H 1
|
||||
#define HAVE_PUTENV 1
|
||||
#define HAVE_STATIC_ASSERT 1
|
||||
#define HAVE_STDINT_H 1
|
||||
#define HAVE_STDIO_H 1
|
||||
#define HAVE_STDLIB_H 1
|
||||
#define HAVE_STRINGS_H 1
|
||||
#define HAVE_STRING_H 1
|
||||
#define HAVE_STRLCAT 1
|
||||
#define HAVE_STRLCPY 1
|
||||
#define HAVE_STRUCT_ADDRINFO 1
|
||||
#define HAVE_STRUCT_IN6_ADDR 1
|
||||
#define HAVE_STRUCT_SOCKADDR_IN6 1
|
||||
#define HAVE_STRUCT_SOCKADDR_STORAGE 1
|
||||
#define HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY 1
|
||||
#define HAVE_SYS_RANDOM_H 1
|
||||
#define HAVE_SYS_SELECT_H 1
|
||||
#define HAVE_SYS_SOCKET_H 1
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
#define HAVE_SYS_UIO_H 1
|
||||
#define HAVE_SYS_WAIT_H 1
|
||||
#define HAVE_UINT16_T 1
|
||||
#define HAVE_UINT32_T 1
|
||||
#define HAVE_UINT8_T 1
|
||||
#define HAVE_U_INT16_T 1
|
||||
#define HAVE_U_INT32_T 1
|
||||
#define HAVE_U_INT8_T 1
|
||||
#define HAVE_UNDERSCORE_STATIC_ASSERT 1
|
||||
#define HAVE_UNISTD_H 1
|
||||
/* NuttX exposes writev(), but keep this port on Dropbear's simpler write()
|
||||
* path until the SSH-to-NSH channel bridge is validated with vectored
|
||||
* writes.
|
||||
*/
|
||||
|
||||
#undef HAVE_WRITEV
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
#define PACKAGE_BUGREPORT ""
|
||||
#define PACKAGE_NAME ""
|
||||
#define PACKAGE_STRING ""
|
||||
#define PACKAGE_TARNAME ""
|
||||
#define PACKAGE_URL ""
|
||||
#define PACKAGE_VERSION ""
|
||||
|
||||
#define SELECT_TYPE_ARG1 int
|
||||
#define SELECT_TYPE_ARG234 (fd_set *)
|
||||
#define SELECT_TYPE_ARG5 (struct timeval *)
|
||||
|
||||
#ifndef PF_UNIX
|
||||
# define PF_UNIX AF_UNIX
|
||||
#endif
|
||||
|
||||
#ifndef GRND_NONBLOCK
|
||||
# define GRND_NONBLOCK O_NONBLOCK
|
||||
#endif
|
||||
|
||||
#define IPPORT_RESERVED 1024
|
||||
|
||||
#define getuid dropbear_getuid
|
||||
#define geteuid dropbear_geteuid
|
||||
#define getpwuid dropbear_getpwuid
|
||||
#define getpwnam dropbear_getpwnam
|
||||
uid_t getuid(void);
|
||||
uid_t geteuid(void);
|
||||
struct passwd *getpwuid(uid_t uid);
|
||||
struct passwd *getpwnam(const char *name);
|
||||
int dropbear_auth_initialize(void);
|
||||
int dropbear_verify_password(const char *username, const char *password);
|
||||
|
||||
#ifndef CONFIG_SCHED_USER_IDENTITY
|
||||
/* NuttX has no supplementary-group support, so getgroups() does not exist. */
|
||||
|
||||
int dropbear_getgroups(int size, gid_t list[]);
|
||||
|
||||
# define getgroups dropbear_getgroups
|
||||
#endif
|
||||
|
||||
#endif /* __APPS_NETUTILS_DROPBEAR_PORT_NUTTX_CONFIG_H */
|
||||
|
|
@ -101,6 +101,10 @@ if(CONFIG_NSH_LIBRARY)
|
|||
endif()
|
||||
endif()
|
||||
|
||||
if(CONFIG_NSH_DROPBEAR)
|
||||
list(APPEND CSRCS nsh_dropbear.c)
|
||||
endif()
|
||||
|
||||
if(NOT CONFIG_NSH_DISABLESCRIPT)
|
||||
list(APPEND CSRCS nsh_test.c)
|
||||
endif()
|
||||
|
|
|
|||
|
|
@ -1201,6 +1201,28 @@ config NSH_DISABLE_TELNETSTART
|
|||
|
||||
endmenu # Telnet Configuration
|
||||
|
||||
menu "Dropbear Configuration"
|
||||
|
||||
config NSH_DROPBEAR
|
||||
bool "Start Dropbear SSH server"
|
||||
default n
|
||||
depends on NETUTILS_DROPBEAR
|
||||
depends on NSH_BUILTIN_APPS
|
||||
depends on !NSH_DISABLEBG
|
||||
select NSH_LOGIN
|
||||
---help---
|
||||
If NSH_DROPBEAR is set to 'y', then NSH starts the Dropbear SSH
|
||||
server automatically.
|
||||
|
||||
config NSH_DISABLE_DROPBEARSTART
|
||||
bool "Disable to start Dropbear"
|
||||
default n
|
||||
depends on NSH_DROPBEAR
|
||||
---help---
|
||||
Determines if NSH starts Dropbear automatically.
|
||||
|
||||
endmenu # Dropbear Configuration
|
||||
|
||||
config NSH_LOGIN
|
||||
bool
|
||||
default n
|
||||
|
|
|
|||
|
|
@ -86,6 +86,10 @@ CSRCS += nsh_telnetlogin.c
|
|||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_NSH_DROPBEAR),y)
|
||||
CSRCS += nsh_dropbear.c
|
||||
endif
|
||||
|
||||
ifneq ($(CONFIG_NSH_DISABLESCRIPT),y)
|
||||
CSRCS += nsh_test.c
|
||||
endif
|
||||
|
|
|
|||
|
|
@ -844,6 +844,10 @@ int nsh_login(FAR struct console_stdio_s *pstate);
|
|||
int nsh_telnetlogin(FAR struct console_stdio_s *pstate);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NSH_DROPBEAR) && !defined(CONFIG_NSH_DISABLE_DROPBEARSTART)
|
||||
int nsh_dropbearstart(void);
|
||||
#endif
|
||||
|
||||
/* Application interface */
|
||||
|
||||
int nsh_command(FAR struct nsh_vtbl_s *vtbl, int argc, FAR char *argv[]);
|
||||
|
|
|
|||
76
nshlib/nsh_dropbear.c
Normal file
76
nshlib/nsh_dropbear.c
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
/****************************************************************************
|
||||
* apps/nshlib/nsh_dropbear.c
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright ownership. The
|
||||
* ASF licenses this file to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the
|
||||
* License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Included Files
|
||||
****************************************************************************/
|
||||
|
||||
#include <nuttx/config.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <debug.h>
|
||||
|
||||
#include "nsh.h"
|
||||
#include "nsh_console.h"
|
||||
|
||||
#ifdef CONFIG_NSH_DROPBEAR
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: nsh_dropbearstart
|
||||
*
|
||||
* Description:
|
||||
* nsh_dropbearstart() starts the Dropbear SSH server. This function
|
||||
* returns immediately after the daemon has been started.
|
||||
*
|
||||
* Returned Values:
|
||||
* Zero is returned if Dropbear was started. A negated errno value will be
|
||||
* returned on failure.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef CONFIG_NSH_DISABLE_DROPBEARSTART
|
||||
int nsh_dropbearstart(void)
|
||||
{
|
||||
FAR struct console_stdio_s *pstate = nsh_newconsole(false);
|
||||
char cmdline[] = CONFIG_NETUTILS_DROPBEAR_PROGNAME " &";
|
||||
int ret;
|
||||
|
||||
DEBUGASSERT(pstate != NULL);
|
||||
|
||||
ninfo("Starting the Dropbear SSH server\n");
|
||||
|
||||
ret = nsh_parse(&pstate->cn_vtbl, cmdline);
|
||||
if (ret < 0)
|
||||
{
|
||||
nerr("ERROR: Failed to start Dropbear: %d\n", ret);
|
||||
}
|
||||
|
||||
nsh_release(&pstate->cn_vtbl);
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CONFIG_NSH_DROPBEAR */
|
||||
|
|
@ -175,4 +175,16 @@ void nsh_initialize(void)
|
|||
|
||||
nsh_telnetstart(AF_UNSPEC);
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_NSH_DROPBEAR) && \
|
||||
!defined(CONFIG_NSH_DISABLE_DROPBEARSTART) && \
|
||||
!defined(CONFIG_NETINIT_NETLOCAL)
|
||||
/* If Dropbear is selected as an SSH front-end, then start the daemon
|
||||
* UNLESS network initialization is deferred via CONFIG_NETINIT_NETLOCAL.
|
||||
* In that case, Dropbear must be started manually with the dropbear
|
||||
* command after the network has been initialized.
|
||||
*/
|
||||
|
||||
nsh_dropbearstart();
|
||||
#endif
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue