busybox/networking/ssl_server.c
Denys Vlasenko 5a1bcdf036 tls: fix cipher-id selection in server mode
ECDSA keys still don't work, and currently will be ignored

function                                             old     new   delta
tls_handshake_as_server                              824    1601    +777
.rodata                                           107764  108007    +243
set_cipher_parameters                                  -     161    +161
packed_usage                                       36072   36146     +74
static.BLOCK_NAMES                                     -      70     +70
client_hello_ciphers                                   -      32     +32
ssl_server_main                                      288     279      -9
load_rsa_priv_key                                    329     282     -47
tls_handshake                                       1676    1530    -146
------------------------------------------------------------------------------
(add/remove: 3/0 grow/shrink: 3/3 up/down: 1357/-202)        Total: 1155 bytes

Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
2026-02-15 15:16:26 +01:00

121 lines
3.2 KiB
C

/*
* Licensed under GPLv2, see file LICENSE in this source tree.
*/
//config:config SSL_SERVER
//config: bool "ssl_server (test TLS server)"
//config: default y
//config: select TLS
//config: help
//config: inetd-style TLS server. Stdin/stdout are already connected
//config: to an accepted TCP socket.
//applet:IF_SSL_SERVER(APPLET(ssl_server, BB_DIR_USR_BIN, BB_SUID_DROP))
//kbuild:lib-$(CONFIG_SSL_SERVER) += ssl_server.o
//usage:#define ssl_server_trivial_usage
//usage: "-f PRIVKEY_CERT.pem PROG ARGS"
//usage:#define ssl_server_full_usage ""
//usage: "Inetd-style TLS server\n"
//usage: "\n -f PEMFILE HAProxy-style CRT file"
/*
# Generate RSA key and certificate
openssl req -x509 -newkey rsa:4096 \
-keyout $HOSTNAME-rsa.key \
-out $HOSTNAME-rsa.crt \
-sha256 -days 9999 -nodes \
-subj /CN=$HOSTNAME \
-addext "subjectAltName=DNS:$HOSTNAME"
# Generate ECDSA key and certificate
openssl genpkey -algorithm EC \
-pkeyopt ec_paramgen_curve:prime256v1 \
-out $HOSTNAME-ecdsa.key
fopenssl req -new -x509 \
-key $HOSTNAME-ecdsa.key \
-out $HOSTNAME-ecdsa.crt \
-sha256 -days 9999 \
-subj "/CN=$HOSTNAME" \
-addext "subjectAltName=DNS:$HOSTNAME"
# Concatenate all these files into PRIVKEY_CERT.pem
{ cat $HOSTNAME-rsa.key
cat $HOSTNAME-rsa.crt
cat $HOSTNAME-ecdsa.key
cat $HOSTNAME-ecdsa.crt
} >PRIVKEY_CERT.pem
*/
#include "libbb.h"
/* TLS server applet.
*
* To generate a test RSA certificate and key:
* openssl req -x509 -newkey rsa:2048 -days 9999 -nodes \
* -subj '/CN=localhost' \
* -out cert.pem -keyout privkey.pem
* Convert to DER format:
* openssl x509 -in cert.pem -outform DER -out cert.der
* openssl rsa -in privkey.pem -outform DER -out privkey.der
*
* Run the server:
* tcpsvd 127.0.0.1 4433 ssl_server -p privkey.der -c cert.der -e echo 'Hello world'
*
* Test with:
* openssl s_client -connect localhost:4433
*/
int ssl_server_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
int ssl_server_main(int argc UNUSED_PARAM, char **argv)
{
struct fd_pair to_prog;
struct fd_pair from_prog;
pid_t pid;
tls_state_t *tls;
const char *pem_file;
unsigned opt;
tls = new_tls_state();
/* "+": stop on first non-option */
opt = getopt32(argv, "+""vf:",
&pem_file
);
argv += optind;
if (!argv[0] || !(opt & 2))
bb_show_usage();
/* In inetd mode, stdin/stdout are the socket.
* But tls_run_copy_loop() needs *non-TLS* fds on STDIN and STDOUT.
* Shuffle them.
*/
xdup2(STDIN_FILENO, 3);
xdup2(STDOUT_FILENO, 4);
tls->ifd = 3;
tls->ofd = 4;
/* This can abort on errors */
tls_handshake_as_server(tls, pem_file);
/* Run PROG, wrap its data in TLS and I/O to socket */
xpiped_pair(to_prog);
xpiped_pair(from_prog);
pid = xvfork();
if (pid == 0) {
/* Child: run the program */
/* NB: close _first_, then move fds! */
close(to_prog.wr);
close(from_prog.rd);
xmove_fd(to_prog.rd, STDIN_FILENO);
xmove_fd(from_prog.wr, STDOUT_FILENO);
BB_EXECVP_or_die(argv);
}
/* Parent: close child ends of pipes */
close(to_prog.rd);
close(from_prog.wr);
/* tls_run_copy_loop() needs non-TLS fds on STDIN and STDOUT */
xmove_fd(from_prog.rd, STDIN_FILENO);
xmove_fd(to_prog.wr, STDOUT_FILENO);
tls_run_copy_loop(tls, /*flags*/ TLSLOOP_EXIT_ON_LOCAL_EOF);
return EXIT_SUCCESS;
}