From 92c81b194f59549e95c663115ecb3a31beccc4de Mon Sep 17 00:00:00 2001
From: Bram Matthys <syzop@vulnscan.org>
Date: Mon, 3 Jan 2022 14:48:00 +0100
Subject: [PATCH] Move "spkifp" to unrealircdctl, so it is available for
 Windows users. For *NIX users no visible change.

---
 src/unrealircdctl.c | 67 ++++++++++++++++++++++++++++++++++++++++++---
 unrealircd.in       | 39 ++++----------------------
 2 files changed, 69 insertions(+), 37 deletions(-)

diff --git a/src/unrealircdctl.c b/src/unrealircdctl.c
index 9b0e30798..948f4acc0 100644
--- a/src/unrealircdctl.c
+++ b/src/unrealircdctl.c
@@ -120,9 +120,9 @@ void unrealircdctl_gencloak(int argc, char *argv[])
 	short has_lower;
 	short has_num;
 
-	fprintf(stderr, "Here are 3 random cloak keys that you can copy-paste to your configuration file:\n\n");
+	printf("Here are 3 random cloak keys that you can copy-paste to your configuration file:\n\n");
 
-	fprintf(stderr, "set {\n\tcloak-keys {\n");
+	printf("set {\n\tcloak-keys {\n");
 	for (keyNum = 0; keyNum < 3; ++keyNum)
 	{
 		has_upper = 0;
@@ -150,12 +150,68 @@ void unrealircdctl_gencloak(int argc, char *argv[])
 		keyBuf[sizeof(keyBuf)-1] = '\0';
 
 		if (has_upper && has_lower && has_num)
-			fprintf(stderr, "\t\t\"%s\";\n", keyBuf);
+			printf("\t\t\"%s\";\n", keyBuf);
 		else
 			/* Try again. For this reason, keyNum must be signed. */
 			keyNum--;
 	}
-	fprintf(stderr, "\t}\n}\n\n");
+	printf("\t}\n}\n\n");
+	exit(0);
+}
+
+void unrealircdctl_spkifp(int argc, char *argv[])
+{
+	char *file = argv[2];
+	SSL_CTX *ctx = SSL_CTX_new(SSLv23_server_method());
+	SSL *ssl;
+	X509 *cert;
+	const char *spkifp;
+
+	if (!ctx)
+	{
+		printf("Internal failure while initializing SSL/TLS library context\n");
+		exit(1);
+	}
+
+	if (!file)
+	{
+		printf("NOTE: This script uses the default certificate location (any set::tls settings\n"
+		       "are ignored). If this is not what you want then specify a certificate\n"
+		       "explicitly like this: ./unrealircd spkifp conf/tls/example.pem\n\n");
+		safe_strdup(file, "tls/server.cert.pem");
+		convert_to_absolute_path(&file, CONFDIR);
+	}
+
+	if (!file_exists(file))
+	{
+		printf("Could not open certificate: %s\n"
+		       "You can specify a certificate like this: ./unrealircd spkifp conf/tls/example.pem\n",
+		       file);
+		exit(1);
+	}
+
+	if (SSL_CTX_use_certificate_chain_file(ctx, file) <= 0)
+	{
+		printf("Could not read certificate '%s'\n", file);
+		exit(1);
+	}
+
+	ssl = SSL_new(ctx);
+	if (!ssl)
+	{
+		printf("Something went wrong when generating the SPKI fingerprint.\n");
+		exit(1);
+	}
+
+	cert = SSL_get_certificate(ssl);
+	spkifp = spki_fingerprint_ex(cert);
+	printf("The SPKI fingerprint for certificate '%s' is:\n"
+	       "%s\n"
+	       "\n"
+	       "You normally add this password on the other side of the link as:\n"
+	       "password \"%s\" { spkifp; };\n"
+	       "\n",
+	       file, spkifp, spkifp);
 	exit(0);
 }
 
@@ -166,6 +222,7 @@ int main(int argc, char *argv[])
 #ifdef _WIN32
 	init_winsock();
 #endif
+	early_init_tls();
 
 	if (argc == 1)
 		unrealircdctl_usage(argv[0]);
@@ -180,6 +237,8 @@ int main(int argc, char *argv[])
 		unrealircdctl_mkpasswd(argc, argv);
 	else if (!strcmp(argv[1], "gencloak"))
 		unrealircdctl_gencloak(argc, argv);
+	else if (!strcmp(argv[1], "spkifp") || !strcmp(argv[1], "spki"))
+		unrealircdctl_spkifp(argc, argv);
 	else
 		unrealircdctl_usage(argv[0]);
 	exit(0);
diff --git a/unrealircd.in b/unrealircd.in
index 674abf8de..6f1df1f27 100644
--- a/unrealircd.in
+++ b/unrealircd.in
@@ -88,11 +88,11 @@ elif [ "$1" = "stop" ] ; then
 		kill -9 `cat $PID_FILE` 1>/dev/null 2>&1
 	fi
 elif [ "$1" = "rehash" ] ; then
-	$UNREALIRCDCTL rehash
+	$UNREALIRCDCTL $*
 elif [ "$1" = "status" ] ; then
-	$UNREALIRCDCTL status
+	$UNREALIRCDCTL $*
 elif [ "$1" = "reloadtls" ] ; then
-	$UNREALIRCDCTL reloadtls
+	$UNREALIRCDCTL $*
 elif [ "$1" = "restart" ] ; then
 	echo "Restarting UnrealIRCd"
 	$0 stop
@@ -114,11 +114,11 @@ elif [ "$1" = "module" ] ; then
 	shift
 	@BINDIR@/unrealircd -m $*
 elif [ "$1" = "mkpasswd" ] ; then
-	$UNREALIRCDCTL mkpasswd $2 $3
+	$UNREALIRCDCTL $*
 elif [ "$1" = "version" ] ; then
 	@BINDIR@/unrealircd -v
 elif [ "$1" = "gencloak" ] ; then
-	$UNREALIRCDCTL gencloak
+	$UNREALIRCDCTL $*
 elif [ "$1" = "backtrace" ] ; then
 	cd @TMPDIR@
 
@@ -209,34 +209,7 @@ __EOF__
 	echo ""
 	echo "Thanks!"
 elif [ "$1" = "spki" -o "$1" = "spkifp" ] ; then
-	CERT="@CONFDIR@/tls/server.cert.pem"
-	if [ "$2" != "" ]; then
-		CERT="$2"
-	else
-		echo "NOTE: This script uses the default certificate location (any set::tls settings"
-		echo "are ignored). If this is not what you want then specify a certificate"
-		echo "explicitly like this: ./unrealircd spkifp conf/tls/example.pem"
-		echo ""
-	fi
-	if [ ! -f "$CERT" ]; then
-		echo "Could not open certificate: $CERT"
-		echo "You can specify a certificate like this: ./unrealircd spkifp conf/tls/example.pem"
-		exit 1
-	fi
-	openssl x509 -noout -in "$CERT" -pubkey | openssl asn1parse -noout -inform pem -out @TMPDIR@/tmp.public.key
-	HASH="`openssl dgst -sha256 -binary @TMPDIR@/tmp.public.key | openssl enc -base64`"
-	rm -f @TMPDIR@/tmp.public.key
-	if [ "$HASH" = "" ]; then
-		echo "Sorry, something went wrong when generating the SPKI fingerprint."
-		echo "Is the 'openssl' tool properly installed?"
-		exit 1
-	fi
-	echo "The SPKI fingerprint for certificate $CERT is:"
-	echo "$HASH"
-	echo ""
-	echo "You normally add this password on the other side of the link as:"
-	echo "password \"$HASH\" { spkifp; };"
-	echo ""
+	$UNREALIRCDCTL $*
 elif [ "$1" = "hot-patch" -o "$1" = "cold-patch" ] ; then
 	if [ ! -d "@BUILDDIR@" ]; then
 		echo "UnrealIRCd source not found. Sorry, it is not possible to patch."