From b1d019146ac8173cfd9e0ec86149d027beefb26f Mon Sep 17 00:00:00 2001
From: 3VAbdAVE <dcollodel@outlook.com>
Date: Mon, 13 May 2024 07:50:46 -0400
Subject: [PATCH] UBNT removed keytool from UnifiOS, modify to use openssl
 PKCS12. Also backup certificates before overwrite, and force unifi to start
 with unifi-core if both are installed.

---
 deploy/unifi.sh | 84 +++++++++++++++++++++++++++++++++++++++----------
 1 file changed, 68 insertions(+), 16 deletions(-)

diff --git a/deploy/unifi.sh b/deploy/unifi.sh
index a864135e..0a574e0d 100644
--- a/deploy/unifi.sh
+++ b/deploy/unifi.sh
@@ -5,6 +5,16 @@
 #   - self-hosted Unifi Controller
 #   - Unifi Cloud Key (Gen1/2/2+)
 #   - Unifi Cloud Key running UnifiOS (v2.0.0+, Gen2/2+ only)
+#     See below regarding keytool. Not tested.
+#   - Unifi Dream Machine
+#       This has not been tested on other "all-in-one" devices such as
+#       UDM Pro or Unifi Express.
+#
+#       OS Version v2.0.0+
+#       Network Application version 7.0.0+
+#       OS version ~3.1 removed java and keytool from the UnifiOS.
+#       Using PKCS12 format keystore appears to work fine.
+#
 # Please report bugs to https://github.com/acmesh-official/acme.sh/issues/3359
 
 #returns 0 means success, otherwise error.
@@ -74,14 +84,16 @@ unifi_deploy() {
   _reload_cmd=""
 
   # Unifi Controller environment (self hosted or any Cloud Key) --
-  # auto-detect by file /usr/lib/unifi/data/keystore:
+  # auto-detect by file /usr/lib/unifi/data/keystore
   _unifi_keystore="${DEPLOY_UNIFI_KEYSTORE:-/usr/lib/unifi/data/keystore}"
   if [ -f "$_unifi_keystore" ]; then
-    _info "Installing certificate for Unifi Controller (Java keystore)"
     _debug _unifi_keystore "$_unifi_keystore"
     if ! _exists keytool; then
-      _err "keytool not found"
-      return 1
+      _do_keytool=0
+      _info "Installing certificate for Unifi Controller (PKCS12 keystore)."
+    else
+      _do_keytool=1
+      _info "Installing certificate for Unifi Controller (Java keystore)"
     fi
     if [ ! -w "$_unifi_keystore" ]; then
       _err "The file $_unifi_keystore is not writable, please change the permission."
@@ -99,22 +111,57 @@ unifi_deploy() {
       return 1
     fi
 
-    _debug "Import into keystore: $_unifi_keystore"
-    if keytool -importkeystore \
-      -deststorepass "$_unifi_keypass" -destkeypass "$_unifi_keypass" -destkeystore "$_unifi_keystore" \
-      -srckeystore "$_import_pkcs12" -srcstoretype PKCS12 -srcstorepass "$_unifi_keypass" \
-      -alias unifi -noprompt; then
-      _debug "Import keystore success!"
-      rm "$_import_pkcs12"
+    # Save the existing keystore in case something goes wrong.
+    mv -f "${_unifi_keystore}" "${_unifi_keystore}"_original
+    _info "Previous keystore saved to ${_unifi_keystore}_original."
+
+    if [ "$_do_keytool" -eq 1 ]; then
+      _debug "Import into keystore: $_unifi_keystore"
+      if keytool -importkeystore \
+        -deststorepass "$_unifi_keypass" -destkeypass "$_unifi_keypass" -destkeystore "$_unifi_keystore" \
+        -srckeystore "$_import_pkcs12" -srcstoretype PKCS12 -srcstorepass "$_unifi_keypass" \
+        -alias unifi -noprompt; then
+        _debug "Import keystore success!"
+      else
+        _err "Error importing into Unifi Java keystore."
+        _err "Please re-run with --debug and report a bug."
+        _info "Restoring original keystore."
+        mv -f "${_unifi_keystore}"_original "${_unifi_keystore}"
+        rm "$_import_pkcs12"
+        return 1
+      fi
     else
-      _err "Error importing into Unifi Java keystore."
-      _err "Please re-run with --debug and report a bug."
-      rm "$_import_pkcs12"
-      return 1
+      _debug "Copying new keystore to $_unifi_keystore"
+      cp -f "$_import_pkcs12" "$_unifi_keystore"
+    fi
+
+    # Update unifi service for certificate cipher compatibility
+    if ${ACME_OPENSSL_BIN:-openssl} pkcs12 \
+      -in "$_import_pkcs12" \
+      -password pass:aircontrolenterprise \
+      -nokeys | ${ACME_OPENSSL_BIN:-openssl} x509 -text \
+      -noout | grep -i "signature" | grep -iq ecdsa >/dev/null 2>&1; then
+      cp -f /usr/lib/unifi/data/system.properties /usr/lib/unifi/data/system.properties_original
+      _info "Updating system configuration for cipher compatibility."
+      _info "Saved original system config to /usr/lib/unifi/data/system.properties_original"
+      sed -i '/unifi\.https\.ciphers/d' /usr/lib/unifi/data/system.properties
+      echo "unifi.https.ciphers=ECDHE-ECDSA-AES256-GCM-SHA384,ECDHE-RSA-AES128-GCM-SHA256" >>/usr/lib/unifi/data/system.properties
+      sed -i '/unifi\.https\.sslEnabledProtocols/d' /usr/lib/unifi/data/system.properties
+      echo "unifi.https.sslEnabledProtocols=TLSv1.3,TLSv1.2" >>/usr/lib/unifi/data/system.properties
+      _info "System configuration updated."
     fi
 
+    rm "$_import_pkcs12"
+
+    # Restarting unifi-core will bring up unifi, doing it out of order results in
+    # a certificate error, and may break wifiman. (unconfirmed)
+    # Restart if we aren't doing unifi-core, otherwise stop and let unifi-core restart it.
     if systemctl -q is-active unifi; then
-      _reload_cmd="${_reload_cmd:+$_reload_cmd && }service unifi restart"
+      if [ ! -f "${DEPLOY_UNIFI_CORE_CONFIG:-/data/unifi-core/config}/unifi-core.key" ]; then
+        _reload_cmd="${_reload_cmd:+$_reload_cmd && }systemctl restart unifi"
+      else
+        _reload_cmd="${_reload_cmd:+$_reload_cmd && }systemctl stop unifi"
+      fi
     fi
     _services_updated="${_services_updated} unifi"
     _info "Install Unifi Controller certificate success!"
@@ -165,6 +212,11 @@ unifi_deploy() {
       return 1
     fi
 
+    # Save the existing certs in case something goes wrong.
+    cp -f "${_unifi_core_config}"/unifi-core.crt "${_unifi_core_config}"/unifi-core_original.crt
+    cp -f "${_unifi_core_config}"/unifi-core.key "${_unifi_core_config}"/unifi-core_original.key
+    _info "Previous certificate and key saved to ${_unifi_core_config}/unifi-core_original.crt/key."
+
     cat "$_cfullchain" >"${_unifi_core_config}/unifi-core.crt"
     cat "$_ckey" >"${_unifi_core_config}/unifi-core.key"