mirror of
https://github.com/apache/nuttx.git
synced 2026-08-01 20:28:58 +00:00
!tools/mkpasswd: PBKDF2 host tool and ROMFS passwd build integration
Add standalone host PBKDF2-HMAC-SHA256 mkpasswd, board_romfs_mkpasswd.sh, and promptpasswd.sh with confirm-password support. Integrate ROMFS passwd generation in Board.mk and CMake. Drop TEA key checks from passwd_keys.mk. Signed-off-by: Abhishek Mishra <mishra.abhishek2808@gmail.com>
This commit is contained in:
parent
82ab33aed6
commit
4761f15b3e
11 changed files with 807 additions and 505 deletions
|
|
@ -107,7 +107,7 @@ ifdef HOSTEXEEXT
|
|||
mkversion: mkversion$(HOSTEXEEXT)
|
||||
endif
|
||||
|
||||
# mkpasswd - Generate a NuttX /etc/passwd entry with TEA-encrypted password
|
||||
# mkpasswd - Generate a NuttX /etc/passwd entry with PBKDF2-HMAC-SHA256 hash
|
||||
|
||||
mkpasswd$(HOSTEXEEXT): mkpasswd.c
|
||||
$(Q) $(HOSTCC) $(HOSTCFLAGS) -o mkpasswd$(HOSTEXEEXT) mkpasswd.c
|
||||
|
|
|
|||
|
|
@ -780,7 +780,7 @@ savedefconfig: apps_preconfig
|
|||
$(Q) ${KCONFIG_ENV} ${KCONFIG_SAVEDEFCONFIG}
|
||||
$(Q) $(call kconfig_tweak_disable,defconfig.tmp,CONFIG_APPS_DIR)
|
||||
$(Q) $(call kconfig_tweak_disable,defconfig.tmp,CONFIG_BASE_DEFCONFIG)
|
||||
$(Q) sed -i.bak -e '/^CONFIG_FSUTILS_PASSWD_KEY[0-9]/d' defconfig.tmp
|
||||
$(Q) sed -i.bak -e '/^CONFIG_FSUTILS_PASSWD_PBKDF2_ITERATIONS=/d' defconfig.tmp
|
||||
$(Q) sed -i.bak -e '/^CONFIG_BOARD_ETC_ROMFS_PASSWD_PASSWORD=/d' defconfig.tmp
|
||||
$(Q) grep "CONFIG_ARCH=" .config >> defconfig.tmp
|
||||
$(Q) grep "^CONFIG_ARCH_CHIP_" .config >> defconfig.tmp; true
|
||||
|
|
@ -803,7 +803,7 @@ savedefconfig: apps_preconfig
|
|||
$(Q) rm -f sortedconfig.tmp
|
||||
$(Q) if grep -q '^CONFIG_BOARD_ETC_ROMFS_PASSWD_ENABLE=y' .config; then \
|
||||
echo "WARNING: CONFIG_BOARD_ETC_ROMFS_PASSWD_PASSWORD was not saved in defconfig."; \
|
||||
echo "WARNING: CONFIG_FSUTILS_PASSWD_KEY1-4 were not saved in defconfig."; \
|
||||
echo "WARNING: CONFIG_FSUTILS_PASSWD_PBKDF2_ITERATIONS was not saved in defconfig."; \
|
||||
echo "WARNING: This is intentional to avoid leaking credentials. Add them manually in local defconfig if needed."; \
|
||||
fi
|
||||
|
||||
|
|
|
|||
62
tools/board_romfs_mkpasswd.sh
Executable file
62
tools/board_romfs_mkpasswd.sh
Executable file
|
|
@ -0,0 +1,62 @@
|
|||
#!/usr/bin/env bash
|
||||
# tools/board_romfs_mkpasswd.sh
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# Ensure the ROMFS root password is configured, then run mkpasswd.
|
||||
# Arguments:
|
||||
# board_romfs_mkpasswd.sh <nuttx-topdir> <passfile> <mkpasswd> <output> [mkpasswd args...]
|
||||
|
||||
set -e
|
||||
|
||||
TOPDIR=$1
|
||||
PASSFILE=$2
|
||||
MKPASSWD=$3
|
||||
OUTPUT=$4
|
||||
shift 4
|
||||
|
||||
CONFIG_FILE="${TOPDIR}/.config"
|
||||
|
||||
read_int_config() {
|
||||
local symbol=$1
|
||||
local default=$2
|
||||
local value
|
||||
|
||||
value=$(grep "^${symbol}=" "${CONFIG_FILE}" 2>/dev/null | cut -d= -f2- | tr -d '"')
|
||||
if [ -z "${value}" ]; then
|
||||
echo "${default}"
|
||||
else
|
||||
echo "${value}"
|
||||
fi
|
||||
}
|
||||
|
||||
ITERATIONS=$(read_int_config CONFIG_FSUTILS_PASSWD_PBKDF2_ITERATIONS 10000)
|
||||
|
||||
"${TOPDIR}/tools/promptpasswd.sh" \
|
||||
--min 8 \
|
||||
--config CONFIG_BOARD_ETC_ROMFS_PASSWD_PASSWORD \
|
||||
--config-file "${CONFIG_FILE}" \
|
||||
--update-config \
|
||||
--prompt "ROMFS root password (min 8 characters): " \
|
||||
--output-file "${PASSFILE}"
|
||||
|
||||
PASSWORD=$(cat "${PASSFILE}")
|
||||
"${MKPASSWD}" --password "${PASSWORD}" \
|
||||
--iterations "${ITERATIONS}" \
|
||||
"$@" -o "${OUTPUT}"
|
||||
rm -f "${PASSFILE}"
|
||||
|
|
@ -356,7 +356,7 @@ echo "CONFIG_BASE_DEFCONFIG=\"$posboardconfig\"" >> "${dest_config}"
|
|||
|
||||
${TOPDIR}/tools/sethost.sh $host $*
|
||||
|
||||
# Supply ROMFS admin password from NUTTX_ROMFS_PASSWD_PASSWORD when absent
|
||||
# Supply ROMFS root password from NUTTX_ROMFS_PASSWD_PASSWORD when absent
|
||||
"${TOPDIR}/tools/update_romfs_password.sh" "${dest_config}"
|
||||
|
||||
# Save the original configuration file without CONFIG_BASE_DEFCONFIG
|
||||
|
|
|
|||
877
tools/mkpasswd.c
877
tools/mkpasswd.c
File diff suppressed because it is too large
Load diff
|
|
@ -3,13 +3,9 @@
|
|||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# Passwd / TEA-key validation and generation. Included from the top-level
|
||||
# Makefile immediately after .config is loaded, BEFORE tools/Unix.mk builds
|
||||
# include/nuttx/config.h. This ordering guarantees that freshly generated
|
||||
# keys are present in .config when config.h is created, so the firmware and
|
||||
# mkpasswd always agree on the same key values in a single make invocation.
|
||||
#
|
||||
# Board.mk only consumes CONFIG_FSUTILS_PASSWD_KEY1..4 in the ROMFS recipe.
|
||||
# ROMFS password validation. Included from the top-level Makefile
|
||||
# immediately after .config is loaded, BEFORE tools/Unix.mk builds
|
||||
# include/nuttx/config.h.
|
||||
############################################################################
|
||||
|
||||
TOPDIR ?= .
|
||||
|
|
@ -28,6 +24,30 @@ else
|
|||
_PASSWD_ENFORCE := $(if $(filter-out $(PASSWD_SKIP_GOALS),$(MAKECMDGOALS)),y,)
|
||||
endif
|
||||
|
||||
ifeq ($(_PASSWD_ENFORCE),y)
|
||||
|
||||
# Reject removed fixed-login symbols left in stale .config or defconfig files.
|
||||
ifneq ($(shell grep -c '^CONFIG_NSH_LOGIN_FIXED=y' $(TOPDIR)/.config 2>/dev/null),0)
|
||||
$(error CONFIG_NSH_LOGIN_FIXED was removed. Enable CONFIG_FSUTILS_PASSWD and CONFIG_NSH_LOGIN_PASSWD, or use CONFIG_NSH_LOGIN_PLATFORM with platform_user_verify().)
|
||||
endif
|
||||
ifneq ($(shell grep -c '^CONFIG_NSH_LOGIN_PASSWORD=' $(TOPDIR)/.config 2>/dev/null),0)
|
||||
$(error CONFIG_NSH_LOGIN_PASSWORD was removed. Set CONFIG_BOARD_ETC_ROMFS_PASSWD_PASSWORD in menuconfig or export NUTTX_ROMFS_PASSWD_PASSWORD.)
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_NSH_CONSOLE_LOGIN),y)
|
||||
ifeq ($(CONFIG_FSUTILS_PASSWD),)
|
||||
$(error NSH console login requires CONFIG_FSUTILS_PASSWD. Fixed login was removed; enable password file support and CONFIG_NSH_LOGIN_PASSWD.)
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_NSH_TELNET_LOGIN),y)
|
||||
ifeq ($(CONFIG_FSUTILS_PASSWD),)
|
||||
$(error NSH telnet login requires CONFIG_FSUTILS_PASSWD. Fixed login was removed; enable password file support and CONFIG_NSH_LOGIN_PASSWD.)
|
||||
endif
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
ifeq ($(CONFIG_BOARD_ETC_ROMFS_PASSWD_ENABLE),y)
|
||||
ifeq ($(_PASSWD_ENFORCE),y)
|
||||
|
||||
|
|
@ -35,43 +55,24 @@ ifeq ($(_PASSWD_ENFORCE),y)
|
|||
$(shell $(TOPDIR)/tools/update_romfs_password.sh $(TOPDIR)/.config >/dev/null 2>&1)
|
||||
include $(TOPDIR)/.config
|
||||
|
||||
# --- password check ---
|
||||
ifeq ($(strip $(patsubst "%",%,$(CONFIG_BOARD_ETC_ROMFS_PASSWD_PASSWORD))),)
|
||||
_PASSWD_HAS_TTY := $(shell test -r /dev/tty && test -w /dev/tty && echo 1)
|
||||
ifneq ($(_PASSWD_HAS_TTY),1)
|
||||
$(info )
|
||||
$(info BUILD ERROR: Admin password not set.)
|
||||
$(info BUILD ERROR: Root password not set.)
|
||||
$(info )
|
||||
$(info Run make menuconfig and set:)
|
||||
$(info Board Selection -> Auto-generate /etc/passwd -> Admin password)
|
||||
$(info Board Selection -> Auto-generate /etc/passwd -> Root password)
|
||||
$(info )
|
||||
$(info For TEA keys, either enable random generation in the same menu,)
|
||||
$(info or set CONFIG_FSUTILS_PASSWD_KEY1..4 under Application Configuration)
|
||||
$(info -> File System Utilities -> Password file support.)
|
||||
$(info For CI or scripted builds, export NUTTX_ROMFS_PASSWD_PASSWORD)
|
||||
$(info (see tools/update_romfs_password.sh).)
|
||||
$(info )
|
||||
$(info Password and keys are not saved in defconfig.)
|
||||
$(info Password is not saved in defconfig.)
|
||||
$(info )
|
||||
$(error Aborting: CONFIG_BOARD_ETC_ROMFS_PASSWD_PASSWORD is not set)
|
||||
endif
|
||||
|
||||
# --- TEA key check / generation ---
|
||||
_PASSWD_KEYS_NEED_SETUP := $(shell \
|
||||
$(TOPDIR)/tools/check_passwd_keys.sh $(TOPDIR)/.config 2>/dev/null)
|
||||
|
||||
ifneq ($(_PASSWD_KEYS_NEED_SETUP),no)
|
||||
ifeq ($(CONFIG_BOARD_ETC_ROMFS_PASSWD_RANDOMIZE_KEYS),y)
|
||||
$(shell $(TOPDIR)/tools/gen_passwd_keys.sh $(TOPDIR)/.config >/dev/null)
|
||||
include $(TOPDIR)/.config
|
||||
else
|
||||
$(info )
|
||||
$(info BUILD ERROR: TEA encryption keys not configured.)
|
||||
$(info )
|
||||
$(info Run make menuconfig and either:)
|
||||
$(info - enable Generate random TEA keys automatically, or)
|
||||
$(info - set CONFIG_FSUTILS_PASSWD_KEY1..4 under Application Configuration)
|
||||
$(info -> File System Utilities -> Password file support)
|
||||
$(info )
|
||||
$(error Aborting: CONFIG_FSUTILS_PASSWD_KEY1..4 must be set to non-default values)
|
||||
endif
|
||||
endif
|
||||
# Interactive builds: board_romfs_mkpasswd.sh / promptpasswd.sh will prompt.
|
||||
endif
|
||||
|
||||
endif
|
||||
endif
|
||||
|
|
|
|||
180
tools/promptpasswd.sh
Executable file
180
tools/promptpasswd.sh
Executable file
|
|
@ -0,0 +1,180 @@
|
|||
#!/usr/bin/env bash
|
||||
# tools/promptpasswd.sh
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# Prompt for a Kconfig password when it is unset or invalid. If no
|
||||
# terminal is available, print an error and exit.
|
||||
#
|
||||
# Usage:
|
||||
# promptpasswd.sh --min <n> [--config <symbol>] [--config-file <file>]
|
||||
# [--update-config] [--prompt <text>] [--output-file <file>]
|
||||
|
||||
set -e
|
||||
|
||||
MIN=8
|
||||
VALUE=""
|
||||
PROMPT="Password: "
|
||||
CONFIG_SYMBOL=""
|
||||
CONFIG_FILE=".config"
|
||||
UPDATE_CONFIG=0
|
||||
OUTPUT_FILE=""
|
||||
|
||||
while [ $# -gt 0 ]; do
|
||||
case "$1" in
|
||||
--min)
|
||||
MIN=$2
|
||||
shift 2
|
||||
;;
|
||||
--value)
|
||||
VALUE=$2
|
||||
shift 2
|
||||
;;
|
||||
--prompt)
|
||||
PROMPT=$2
|
||||
shift 2
|
||||
;;
|
||||
--config)
|
||||
CONFIG_SYMBOL=$2
|
||||
shift 2
|
||||
;;
|
||||
--config-file)
|
||||
CONFIG_FILE=$2
|
||||
shift 2
|
||||
;;
|
||||
--update-config)
|
||||
UPDATE_CONFIG=1
|
||||
shift
|
||||
;;
|
||||
--output-file)
|
||||
OUTPUT_FILE=$2
|
||||
shift 2
|
||||
;;
|
||||
*)
|
||||
echo "promptpasswd.sh: unknown option: $1" >&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
validate_password() {
|
||||
local pw="$1"
|
||||
local ok=0
|
||||
|
||||
if [ ${#pw} -lt "${MIN}" ]; then
|
||||
echo "Error: password must be at least ${MIN} characters" >&2
|
||||
ok=1
|
||||
fi
|
||||
|
||||
if ! printf '%s' "$pw" | grep -q '[A-Z]'; then
|
||||
echo "Error: password must contain at least one uppercase letter (A-Z)" >&2
|
||||
ok=1
|
||||
fi
|
||||
|
||||
if ! printf '%s' "$pw" | grep -q '[a-z]'; then
|
||||
echo "Error: password must contain at least one lowercase letter (a-z)" >&2
|
||||
ok=1
|
||||
fi
|
||||
|
||||
if ! printf '%s' "$pw" | grep -q '[0-9]'; then
|
||||
echo "Error: password must contain at least one digit (0-9)" >&2
|
||||
ok=1
|
||||
fi
|
||||
|
||||
if ! printf '%s' "$pw" | grep -q '[^a-zA-Z0-9]'; then
|
||||
echo "Error: password must contain at least one special character" \
|
||||
"(!@#\$%^&*()_+-=[]{}|;:,.<>?)" >&2
|
||||
ok=1
|
||||
fi
|
||||
|
||||
return "${ok}"
|
||||
}
|
||||
|
||||
if [ -n "${CONFIG_SYMBOL}" ] && [ -z "${VALUE}" ] && [ -f "${CONFIG_FILE}" ]; then
|
||||
VALUE=$(grep "^${CONFIG_SYMBOL}=" "${CONFIG_FILE}" 2>/dev/null | cut -d= -f2- | tr -d '"')
|
||||
fi
|
||||
|
||||
if [ -n "${VALUE}" ] && validate_password "${VALUE}"; then
|
||||
if [ -n "${OUTPUT_FILE}" ]; then
|
||||
umask 077
|
||||
printf '%s' "${VALUE}" > "${OUTPUT_FILE}"
|
||||
else
|
||||
printf '%s' "${VALUE}"
|
||||
fi
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# Make recipe shells are not connected to the terminal on stdin, so test /dev/tty
|
||||
# instead of [ -t 0 ] when deciding whether an interactive prompt is possible.
|
||||
|
||||
INTERACTIVE=0
|
||||
if [ -r /dev/tty ] && [ -w /dev/tty ]; then
|
||||
INTERACTIVE=1
|
||||
fi
|
||||
|
||||
if [ "${INTERACTIVE}" -eq 0 ]; then
|
||||
echo "" >&2
|
||||
if [ -n "${CONFIG_SYMBOL}" ]; then
|
||||
echo "ERROR: ${CONFIG_SYMBOL} must be at least ${MIN} characters and" >&2
|
||||
echo "contain uppercase, lowercase, digit, and special character." >&2
|
||||
else
|
||||
echo "ERROR: Password must be at least ${MIN} characters and contain" >&2
|
||||
echo "uppercase, lowercase, digit, and special character." >&2
|
||||
fi
|
||||
echo "Set it with 'make menuconfig' or edit .config, then rebuild." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
PASSWORD=""
|
||||
while true; do
|
||||
printf '%s' "${PROMPT}" >/dev/tty
|
||||
IFS= read -r -s PASSWORD </dev/tty
|
||||
echo "" >/dev/tty
|
||||
if ! validate_password "${PASSWORD}"; then
|
||||
echo "Please try again." >&2
|
||||
PASSWORD=""
|
||||
continue
|
||||
fi
|
||||
|
||||
while true; do
|
||||
printf 'Confirm password: ' >/dev/tty
|
||||
IFS= read -r -s PASSWORD2 </dev/tty
|
||||
echo "" >/dev/tty
|
||||
if [ "${PASSWORD}" = "${PASSWORD2}" ]; then
|
||||
break
|
||||
fi
|
||||
echo "Passwords do not match. Please try again." >&2
|
||||
PASSWORD=""
|
||||
break
|
||||
done
|
||||
|
||||
if [ -n "${PASSWORD}" ]; then
|
||||
break
|
||||
fi
|
||||
done
|
||||
|
||||
if [ "${UPDATE_CONFIG}" -eq 1 ] && [ -n "${CONFIG_SYMBOL}" ]; then
|
||||
kconfig-tweak --file "${CONFIG_FILE}" --set-str "${CONFIG_SYMBOL}" "${PASSWORD}"
|
||||
fi
|
||||
|
||||
if [ -n "${OUTPUT_FILE}" ]; then
|
||||
umask 077
|
||||
printf '%s' "${PASSWORD}" > "${OUTPUT_FILE}"
|
||||
else
|
||||
printf '%s' "${PASSWORD}"
|
||||
fi
|
||||
|
|
@ -19,7 +19,7 @@
|
|||
# Usage:
|
||||
# update_romfs_password.sh <path-to-.config>
|
||||
#
|
||||
# When CONFIG_BOARD_ETC_ROMFS_PASSWD_ENABLE=y and the admin password is not
|
||||
# When CONFIG_BOARD_ETC_ROMFS_PASSWD_ENABLE=y and the root password is not
|
||||
# set in .config, copy NUTTX_ROMFS_PASSWD_PASSWORD into .config. This is the
|
||||
# supported way to supply build-time credentials that must not live in defconfig
|
||||
# (CI, automation, local scripts). No-op when the password is already set or
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue