Merge pull request #8070 from jefferyto/stunnel-init
stunnel: Update init script
This commit is contained in:
commit
8b7ae5c40d
3 changed files with 330 additions and 106 deletions
|
@ -9,7 +9,7 @@ include $(TOPDIR)/rules.mk
|
|||
|
||||
PKG_NAME:=stunnel
|
||||
PKG_VERSION:=5.49
|
||||
PKG_RELEASE:=1
|
||||
PKG_RELEASE:=2
|
||||
|
||||
PKG_LICENSE:=GPL-2.0+
|
||||
PKG_MAINTAINER:=Florian Eckert <fe@dev.tdt.de>
|
||||
|
|
|
@ -1,180 +1,402 @@
|
|||
#!/bin/sh /etc/rc.common
|
||||
# Copyright (C) 2006-2008 OpenWrt.org
|
||||
# Copyright (C) 2019 Jeffery To
|
||||
|
||||
START=90
|
||||
USE_PROCD=1
|
||||
|
||||
PID_FILE="/var/run/stunnel.pid"
|
||||
CONF_FILE="/tmp/stunnel.conf"
|
||||
PID_FILE="/var/run/stunnel/stunnel.pid"
|
||||
CONF_FILE="/var/etc/stunnel.conf"
|
||||
BIN="/usr/bin/stunnel"
|
||||
SERVICE_SECTION_FOUND=0
|
||||
CONF_FILE_CREATED=
|
||||
HAVE_ALT_CONF_FILE=
|
||||
SERVICE_SECTION_FOUND=
|
||||
|
||||
global_defs() {
|
||||
local debug compression
|
||||
validate_globals_section() {
|
||||
uci_load_validate stunnel globals "$1" "$2" \
|
||||
'alt_config_file:file' \
|
||||
\
|
||||
'compression:or("deflate","zlib")' \
|
||||
'EGD:string' \
|
||||
'engine:string' \
|
||||
'engineCtrl:string' \
|
||||
'engineDefault:list(or("ALL","CIPHERS","DH","DIGESTS","DSA","ECDH","ECDSA","PKEY","PKEY_ASN1","PKEY_CRYPTO","RAND","RSA"))' \
|
||||
'log:or("append","overwrite")' \
|
||||
'output:string' \
|
||||
'RNDbytes:uinteger' \
|
||||
'RNDfile:string' \
|
||||
'RNDoverwrite:bool' \
|
||||
'setgid:or(string,uinteger)' \
|
||||
'setuid:or(string,uinteger)' \
|
||||
'syslog:bool' \
|
||||
;
|
||||
}
|
||||
|
||||
config_get alt_config_file 'globals' alt_config_file
|
||||
[ -z "$alt_config_file" ] || return 0
|
||||
validate_service_section() {
|
||||
uci_load_validate stunnel service "$1" "$2" \
|
||||
'enabled:bool:1' \
|
||||
\
|
||||
'setgid:or(string,uinteger)' \
|
||||
'setuid:or(string,uinteger)' \
|
||||
;
|
||||
}
|
||||
|
||||
# Set default settings
|
||||
printf "foreground = yes\n" >> "$CONF_FILE"
|
||||
printf "pid = %s\n" "$PID_FILE" >> "$CONF_FILE"
|
||||
printf "syslog = yes\n" >> "$CONF_FILE"
|
||||
validate_service_options() {
|
||||
uci_load_validate stunnel "$1" "$2" "$3" \
|
||||
'accept_host:host' \
|
||||
'accept_port:port' \
|
||||
'CAfile:string' \
|
||||
'CApath:string' \
|
||||
'cert:string' \
|
||||
'checkEmail:list(string)' \
|
||||
'checkHost:list(host)' \
|
||||
'checkIP:list(ipaddr)' \
|
||||
'ciphers:list(string)' \
|
||||
'client:bool' \
|
||||
'config:list(string)' \
|
||||
'connect:list(string)' \
|
||||
'CRLfile:string' \
|
||||
'CRLpath:string' \
|
||||
'curve:string' \
|
||||
'debug:or(range(0,7),string)' \
|
||||
'delay:bool' \
|
||||
'engineId:string' \
|
||||
'engineNum:and(uinteger,min(1))' \
|
||||
'exec:string' \
|
||||
'execArgs:string' \
|
||||
'failover:or("prio","rr")' \
|
||||
'ident:string' \
|
||||
'include:directory' \
|
||||
'key:string' \
|
||||
'local:host' \
|
||||
'logId:or("process","sequential","thread","unique")' \
|
||||
'OCSP:string' \
|
||||
'OCSPaia:bool' \
|
||||
'OCSPflag:list(or("NOCASIGN","NOCERTS","NOCHAIN","NOCHECKS","NODELEGATED","NOEXPLICIT","NOINTERN","NOSIGS","NOTIME","NOVERIFY","RESPID_KEY","TRUSTOTHER"))' \
|
||||
'OCSPnonce:bool' \
|
||||
'options:list(string) ' \
|
||||
'protocol:or("cifs","connect","imap","nntp","pgsql","pop3","proxy","smtp","socks")' \
|
||||
'protocolAuthentication:or("basic","login","ntlm","plain")' \
|
||||
'protocolDomain:hostname' \
|
||||
'protocolHost_host:host' \
|
||||
'protocolHost_port:port' \
|
||||
'protocolPassword:string' \
|
||||
'protocolUsername:string' \
|
||||
'PSKidentity:string' \
|
||||
'PSKsecrets:string' \
|
||||
'pty:bool' \
|
||||
'redirect_host:host' \
|
||||
'redirect_port:port' \
|
||||
'renegotiation:bool' \
|
||||
'requireCert:bool' \
|
||||
'reset:bool' \
|
||||
'retry:bool' \
|
||||
'service:string' \
|
||||
'sessionCacheSize:uinteger' \
|
||||
'sessionCacheTimeout:uinteger' \
|
||||
'sessiond_host:host' \
|
||||
'sessiond_port:port' \
|
||||
'sni:list(string)' \
|
||||
'socket:list(string)' \
|
||||
'sslVersion:or("all","SSLv2","SSLv3","TLSv1","TLSv1.1","TLSv1.2")' \
|
||||
'stack:uinteger' \
|
||||
'TIMEOUTbusy:uinteger' \
|
||||
'TIMEOUTclose:uinteger' \
|
||||
'TIMEOUTconnect:uinteger' \
|
||||
'TIMEOUTidle:uinteger' \
|
||||
'transparent:or("both","destination","none","source")' \
|
||||
'verifyChain:bool' \
|
||||
'verifyPeer:bool' \
|
||||
;
|
||||
}
|
||||
|
||||
config_get debug 'globals' debug '5'
|
||||
printf "debug = %s\n" "$debug" >> "$CONF_FILE"
|
||||
validate_globals_section_service_options() {
|
||||
validate_service_options globals "$@"
|
||||
}
|
||||
|
||||
config_get compression 'globals' compression
|
||||
[ -z "$compression" ] || printf "compression = %s\n" "$compression" >> "$CONF_FILE"
|
||||
validate_service_section_service_options() {
|
||||
validate_service_options service "$@"
|
||||
}
|
||||
|
||||
print_options() {
|
||||
local config=$1
|
||||
shift
|
||||
for opt in "$@"; do
|
||||
local $opt
|
||||
local value
|
||||
local is_boolean=0
|
||||
local _opt
|
||||
local _value
|
||||
for _opt in $*; do
|
||||
eval "_value=\$$_opt"
|
||||
[ -z "$_value" ] || echo "$_opt = $_value" >> "$CONF_FILE"
|
||||
done
|
||||
}
|
||||
|
||||
if [ "${opt:0:5}" == "bool_" ]; then
|
||||
opt="${opt:5}"
|
||||
is_boolean=1
|
||||
fi
|
||||
|
||||
config_get "value" "$config" "$opt"
|
||||
[ -z "$value" ] || {
|
||||
if [ "$value" = '1' ] && [ "$is_boolean" -eq "1" ]; then
|
||||
value="yes"
|
||||
elif [ "$value" = '0' ] && [ "$is_boolean" -eq "1" ] ; then
|
||||
value="no"
|
||||
fi
|
||||
printf "%s = %s\n" "$opt" "$value" >> "$CONF_FILE"
|
||||
print_bool_options() {
|
||||
local _opt
|
||||
local _bool
|
||||
local _value
|
||||
for _opt in $*; do
|
||||
eval "_bool=\$$_opt"
|
||||
[ -z "$_bool" ] || {
|
||||
_value=no
|
||||
[ "$_bool" != 1 ] || _value=yes
|
||||
echo "$_opt = $_value" >> "$CONF_FILE"
|
||||
}
|
||||
done
|
||||
}
|
||||
|
||||
print_list() {
|
||||
local config=$1
|
||||
shift
|
||||
for opt in "$@"; do
|
||||
local $opt
|
||||
local elements
|
||||
config_get "elements" "$config" "$opt"
|
||||
for element in $elements; do
|
||||
printf "%s = %s\n" "$opt" "$element" >> "$CONF_FILE"
|
||||
print_lists_map() {
|
||||
local _opt
|
||||
local _values
|
||||
local _value
|
||||
for _opt in $*; do
|
||||
eval "_values=\$$_opt"
|
||||
for _value in $_values; do
|
||||
echo "$_opt = $_value" >> "$CONF_FILE"
|
||||
done
|
||||
done
|
||||
}
|
||||
|
||||
print_list_colon() {
|
||||
local config=$1
|
||||
local value
|
||||
print_lists_reduce() {
|
||||
local _delim="$1"
|
||||
local _opt
|
||||
local _value
|
||||
local _values
|
||||
local _v
|
||||
shift
|
||||
for opt in "$@"; do
|
||||
local $opt
|
||||
local elements
|
||||
config_get "elements" "$config" "$opt"
|
||||
for element in $elements; do
|
||||
value="${value}:${element}"
|
||||
for _opt in $*; do
|
||||
_value=
|
||||
eval "_values=\$$_opt"
|
||||
for _v in $_values; do
|
||||
_value=$_value$_delim$_v
|
||||
done
|
||||
printf "%s = %s\n" "$opt" "${value#*:}" >> "$CONF_FILE"
|
||||
_value=${_value#$_delim}
|
||||
[ -z "$_value" ] || echo "$_opt = $_value" >> "$CONF_FILE"
|
||||
done
|
||||
}
|
||||
|
||||
service_section() {
|
||||
local cfg="$1"
|
||||
local accept_host accept_port enabled
|
||||
print_host_port() {
|
||||
local _opt
|
||||
local _host
|
||||
local _port
|
||||
for _opt in $*; do
|
||||
eval "_host=\${${_opt}_host}"
|
||||
eval "_port=\${${_opt}_port}"
|
||||
[ -z "$_host" ] || [ -z "$_port" ] || echo "$_opt = $_host:$_port" >> "$CONF_FILE"
|
||||
done
|
||||
}
|
||||
|
||||
config_get_bool enabled "$cfg" 'enabled' '1'
|
||||
[ ${enabled} -gt 0 ] || return 0
|
||||
print_optional_host_port() {
|
||||
local _opt
|
||||
local _host
|
||||
local _port
|
||||
local _value
|
||||
for _opt in $*; do
|
||||
eval "_host=\${${_opt}_host}"
|
||||
eval "_port=\${${_opt}_port}"
|
||||
[ -z "$_port" ] || {
|
||||
_value=$_port
|
||||
[ -z "$_host" ] || _value=$_host:$_port
|
||||
echo "$_opt = $_value" >> "$CONF_FILE"
|
||||
}
|
||||
done
|
||||
}
|
||||
|
||||
SERVICE_SECTION_FOUND=1
|
||||
printf "\n" >> "$CONF_FILE"
|
||||
printf "[%s]\n" "$cfg" >> "$CONF_FILE"
|
||||
print_global_options() {
|
||||
print_options \
|
||||
compression \
|
||||
EGD \
|
||||
engine \
|
||||
engineCtrl \
|
||||
log \
|
||||
output \
|
||||
RNDbytes \
|
||||
RNDfile \
|
||||
RNDoverwrite \
|
||||
;
|
||||
|
||||
config_get accept_host "$cfg" accept_host 'localhost'
|
||||
config_get accept_port "$cfg" accept_port
|
||||
printf "accept = %s:%s\n" "$accept_host" "$accept_port" >> "$CONF_FILE"
|
||||
print_bool_options \
|
||||
syslog \
|
||||
;
|
||||
|
||||
print_options "$cfg" CApath \
|
||||
print_lists_reduce , \
|
||||
engineDefault \
|
||||
;
|
||||
}
|
||||
|
||||
print_service_options() {
|
||||
[ "$2" = 0 ] || {
|
||||
echo "validation failed"
|
||||
return 1
|
||||
}
|
||||
|
||||
print_options \
|
||||
CAfile \
|
||||
CApath \
|
||||
cert \
|
||||
CRLpath \
|
||||
CRLfile \
|
||||
CRLpath \
|
||||
curve \
|
||||
logId \
|
||||
debug \
|
||||
logId \
|
||||
engineId \
|
||||
engineNum \
|
||||
exec \
|
||||
execArgs \
|
||||
failover \
|
||||
ident \
|
||||
include \
|
||||
key \
|
||||
local \
|
||||
OCSP \
|
||||
protocol \
|
||||
protocolAuthentication \
|
||||
protocolDomain \
|
||||
protocolPassword \
|
||||
protocolUsername \
|
||||
PSKidentity \
|
||||
PSKsecrets \
|
||||
service \
|
||||
sessionCacheSize \
|
||||
sessionCacheTimeout \
|
||||
setgid \
|
||||
setuid \
|
||||
sslVersion \
|
||||
stack \
|
||||
TIMEOUTbusy \
|
||||
TIMEOUTclose \
|
||||
TIMEOUTconnect \
|
||||
TIMEOUTidle \
|
||||
bool_delay \
|
||||
bool_libwrap \
|
||||
bool_reset \
|
||||
bool_requireCert \
|
||||
bool_verifyChain \
|
||||
bool_verifyPeer \
|
||||
bool_client
|
||||
transparent \
|
||||
;
|
||||
|
||||
print_list "$cfg" checkEmail \
|
||||
print_bool_options \
|
||||
client \
|
||||
delay \
|
||||
OCSPaia \
|
||||
OCSPnonce \
|
||||
pty \
|
||||
renegotiation \
|
||||
requireCert \
|
||||
reset \
|
||||
retry \
|
||||
verifyChain \
|
||||
verifyPeer \
|
||||
;
|
||||
|
||||
print_lists_map \
|
||||
checkEmail \
|
||||
checkHost \
|
||||
checkIP \
|
||||
config \
|
||||
connect \
|
||||
options
|
||||
OCSPflag \
|
||||
options \
|
||||
sni \
|
||||
socket \
|
||||
;
|
||||
|
||||
print_list_colon "$cfg" ciphers
|
||||
print_lists_reduce : \
|
||||
ciphers \
|
||||
;
|
||||
|
||||
print_host_port \
|
||||
protocolHost \
|
||||
sessiond \
|
||||
;
|
||||
|
||||
print_optional_host_port \
|
||||
accept \
|
||||
redirect \
|
||||
;
|
||||
}
|
||||
|
||||
process_config() {
|
||||
local alt_config_file
|
||||
create_conf_file() {
|
||||
[ -n "$CONF_FILE_CREATED" ] || {
|
||||
mkdir -p "$(dirname "$CONF_FILE")"
|
||||
echo "; STunnel configuration file generated by uci" > "$CONF_FILE"
|
||||
echo "; Written $(date +'%c')" >> "$CONF_FILE"
|
||||
echo >> "$CONF_FILE"
|
||||
echo "foreground = quiet" >> "$CONF_FILE"
|
||||
echo "pid = $PID_FILE" >> "$CONF_FILE"
|
||||
CONF_FILE_CREATED=1
|
||||
}
|
||||
}
|
||||
|
||||
rm -f "$CONF_FILE"
|
||||
global_defs() {
|
||||
local pid_dir
|
||||
|
||||
# First line
|
||||
printf "; STunnel configuration file generated by uci\n" > "$CONF_FILE"
|
||||
printf "; Written %s\n\n" "$(date +'%c')" >> "$CONF_FILE"
|
||||
[ "$2" = 0 ] || {
|
||||
echo "validation failed"
|
||||
return 1
|
||||
}
|
||||
|
||||
[ -f /etc/config/stunnel ] || return 0
|
||||
# If the first globals section has alt_config_file, don't process any more globals
|
||||
[ -z "$HAVE_ALT_CONF_FILE" ] || return 0
|
||||
|
||||
config_load stunnel
|
||||
global_defs
|
||||
|
||||
# If "alt_config_file" specified, use that instead
|
||||
[ -n "$alt_config_file" ] && [ -f "$alt_config_file" ] && {
|
||||
rm -f "$CONF_FILE"
|
||||
# If "alt_config_file" specified in the first globals section, use that instead
|
||||
[ -z "$alt_config_file" ] || [ -n "$CONF_FILE_CREATED" ] || {
|
||||
# Symlink "alt_config_file" since it's a bit easier and safer
|
||||
ln -s "$alt_config_file" "$CONF_FILE"
|
||||
# Set section found to start service user hopfully knows what you does
|
||||
# Set section found to start service, user hopefully knows what they are doing
|
||||
SERVICE_SECTION_FOUND=1
|
||||
CONF_FILE_CREATED=1
|
||||
HAVE_ALT_CONF_FILE=1
|
||||
return 0
|
||||
}
|
||||
|
||||
config_foreach service_section service
|
||||
pid_dir="$(dirname "$PID_FILE")"
|
||||
mkdir -p "$pid_dir"
|
||||
[ -z "$setuid" ] || chown "$setuid" "$pid_dir"
|
||||
[ -z "$setgid" ] || chown ":$setgid" "$pid_dir"
|
||||
|
||||
create_conf_file
|
||||
print_global_options
|
||||
validate_service_options globals "$1" print_service_options
|
||||
}
|
||||
|
||||
service_section() {
|
||||
[ "$2" = 0 ] || {
|
||||
echo "validation failed"
|
||||
return 1
|
||||
}
|
||||
|
||||
[ "$enabled" = 1 ] || return 0
|
||||
|
||||
SERVICE_SECTION_FOUND=1
|
||||
echo >> "$CONF_FILE"
|
||||
echo "[$1]" >> "$CONF_FILE"
|
||||
|
||||
validate_service_options service "$1" print_service_options
|
||||
}
|
||||
|
||||
service_triggers() {
|
||||
procd_add_reload_trigger "stunnel"
|
||||
procd_add_reload_trigger stunnel
|
||||
|
||||
procd_open_validate
|
||||
validate_globals_section
|
||||
validate_globals_section_service_options
|
||||
validate_service_section
|
||||
validate_service_section_service_options
|
||||
procd_close_validate
|
||||
}
|
||||
|
||||
start_service() {
|
||||
process_config
|
||||
rm -f "$CONF_FILE"
|
||||
config_load stunnel
|
||||
|
||||
if [ "$SERVICE_SECTION_FOUND" = 1 ]; then
|
||||
procd_open_instance
|
||||
procd_set_param command "$BIN"
|
||||
procd_append_param command "$CONF_FILE"
|
||||
procd_set_param respawn
|
||||
procd_set_param file "$CONF_FILE"
|
||||
procd_close_instance
|
||||
else
|
||||
config_foreach validate_globals_section globals global_defs
|
||||
|
||||
[ -n "$HAVE_ALT_CONF_FILE" ] || {
|
||||
create_conf_file
|
||||
config_foreach validate_service_section service service_section
|
||||
}
|
||||
|
||||
[ -n "$SERVICE_SECTION_FOUND" ] || {
|
||||
logger -t stunnel -p daemon.info "No uci service section enabled or found!"
|
||||
fi
|
||||
return 1
|
||||
}
|
||||
|
||||
procd_open_instance
|
||||
procd_set_param command "$BIN"
|
||||
procd_append_param command "$CONF_FILE"
|
||||
procd_set_param respawn
|
||||
procd_set_param file "$CONF_FILE"
|
||||
procd_close_instance
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
config globals 'globals'
|
||||
option alt_config_file '/etc/stunnel/stunnel.conf'
|
||||
option debug '5'
|
||||
#option alt_config_file '/etc/stunnel/stunnel.conf'
|
||||
option setuid 'nobody'
|
||||
option setgid 'nogroup'
|
||||
|
||||
config service 'dummy'
|
||||
option enabled '1'
|
||||
option client '1'
|
||||
option accept_host 'localhost'
|
||||
option accept_port '6000'
|
||||
|
|
Loading…
Reference in a new issue