#!/bin/bash

#PASSWORD_PROMPT=""
APPNAME=""
IGNORE_NLA_REQUEST="y"
RETRY_WITH_TOFU=""
ASK_PASS="y"

print_help() {
cat <<EOF
This program wraps a bit of graphical fluff around xfreerdp using kdialog and notify-send to make it useable in a regular office context.

Usage: foxde-xfreerdp-gui [--ask-pass-prompt <remote-name>] [--] <<xfreerdp-options>>
       foxde-xfreerdp-gui --help

Options:

--gui <remote-name>
	will trigger a ui wrapper that asks for a password before connecting.
	To detect some errors (currently just an unexpected certificate)
	a logfile will be written to \$TEMP/xfreerdp-gui-log.XXXXXXXXXX
	This log will be left behind if xfreerdp exits with an error code.

--no-pass-prompt
	Disables the wrapper asking for a password.

--allow-nla-request
	if this is enabled (with --ask-pass-prompt) this script will return
	* 101, pasword expired + no-nla request
	* 102, generic no-nla request
	* 103, nla requested

--retry-with-tofu
	Will retry connections using tofu pinning if CA-validation fails.
	This prioritizes a working connection over security.
		
Exit Codes:

Usually returns what xfreerdp would return.

77	Certificate mismatch for tofu mode
	see ~/.config/freerdp/known_hosts2
EOF
}

while [ "$#" -gt 0 ]; do
  case "$1" in
	--help) print_help; exit 0;;
    --no-pass-prompt) ASK_PASS=""; shift 1;;
	--gui) APPNAME="$2"; shift 2;;
    --allow-nla-request) IGNORE_NLA_REQUEST=""; shift 1;;
    --retry-with-tofu) RETRY_WITH_TOFU="y"; shift 1;;

	--) shift 1; break ;;
    *) break;
  esac
done

DO_RETRY=""

get_error_message_for_code() {
	printf "Fehlercode: %d - " "$1"
	# See https://github.com/FreeRDP/FreeRDP/blob/90b3bf4891e426d422ddb0581560450013832e5e/client/X11/xfreerdp.h
	case "$1" in
		0) echo "Exit Success" ;;
		1) echo "Exit Disconnect" ;;
		2) echo "Logoff" ;;
		3) echo "Idle Timeout" ;;
		4) echo "Logon Timeout" ;;
		5) echo "Conn Replaced" ;;
		6) echo "Out of Memory" ;;
		7) echo "Conn Denied" ;;
		8) echo "Conn Denied Fips" ;;
		9) echo "User Privileges" ;;
		10) echo "Fresh Credentials Required" ;;
		11) echo "Disconnect by User" ;;

		# section 16-31: license error set
		16) echo "License Internal" ;;
		17) echo "License no License Server" ;;
		18) echo "License no License" ;;
		19) echo "License Bad Client Msg" ;;
		20) echo "License Hwid Doesnt Match" ;;
		21) echo "License Bad Client" ;;
		22) echo "License can't Finish Protocol" ;;
		23) echo "License Client Ended Protocol" ;;
		24) echo "License Bad Client Encryption" ;;
		25) echo "License can't Upgrade" ;;
		26) echo "License No Remote Connections" ;;

		# section 32-127: RDP protocol error set
		32) echo "Rdp protocol error set" ;;

		# section 128-254: xfreerdp specific exit codes
		128) echo "Parse Arguments" ;;
		129) echo "Memory" ;;
		130) echo "Protocol" ;;
		131) echo "Connction Failed" ;;
		132) echo "Auth Failure" ;;

		134) echo "Password Expired" ;;

		# Connection issues
		140) echo "DNS-Name not found" ;;

		143) echo "TLS-Conection failed" ;;
		147) echo "Transport connect failed" ;;

		*) echo "Unbekannt" ;;
	esac
}

if [ -z "$APPNAME" ] ; then
	xfreerdp "$@"
else
	LOGFILE="$(mktemp --tmpdir "xfreerdp-gui-log.$(date "+%Y-%m-%d_%H:%M").XXXXXXXXXX")"
	echo "Writing Logfile: $LOGFILE"
	kdialog --version || exit 100
	RETCODE=131
	while [ "$RETCODE" -eq 131 ] || [ -n "$DO_RETRY" ] ; do
		if [ -n "$ASK_PASS" ] ; then
			if ! [ "$DO_RETRY" = "keep-password" ]; then
				PASSWORD="$(kdialog --password "Passwort für $APPNAME" --title "Remotedesktopverbindung")"
			fi
			if [[ -z "$PASSWORD" ]] ; then
				notify-send "(RDP) Abgebrochen" "Es wird keine Verbindung zu $APPNAME aufgebaut."
				exit
			fi
		fi
		DO_RETRY=""
		date +"%Y-%m-%d %H:%M:%S" > "$LOGFILE"
		echo "Connecting to $APPNAME using freerdp $*" | tee "$LOGFILE"
		xfreerdp "$@" /from-stdin:force 2>> "$LOGFILE" >>"$LOGFILE" <<EOF
$PASSWORD
EOF
		RETCODE="$?"
		cat "$LOGFILE"
		printf "Freerdp exited with exit code: %d\n\n\n" "$RETCODE"
		if grep -q "certificate does not match the certificate used for previous connections" "$LOGFILE" ; then
			kdialog --error "Der Server kann sich aktuell nicht ausweisen, weswegen die Verbindung beendet wurde.\nBitte kontaktiere die IT-Abteilung." --title "Verbindung fehlgeschlagen."
			exit 77
		elif [ -z "$IGNORE_NLA_REQUEST" ] && grep -q "Error: HYBRID_REQUIRED_BY_SERVER" "$LOGFILE" ; then
			echo "Received a enable-NLA Request!"
			exit 103
		elif [ "$RETCODE" -eq 148 ] || [ "$RETCODE" -eq 134 ] || grep -q "ERRCONNECT_PASSWORD_EXPIRED" "$LOGFILE"; then
			if [ -z "$IGNORE_NLA_REQUEST" ] && grep -q "rdp_recv_callback: CONNECTION_STATE_NLA" "$LOGFILE"; then
				echo "Received No-NLA Request! (and password is expired)"
				exit 101
			else
				kdialog --title "(RDP) Passwort abgelaufen" --error "Dein Passwort für $APPNAME ist abgelaufen,\nbitte kontaktiere die IT-Abteilung.\n\n$(get_error_message_for_code "$RETCODE")"
			fi
			exit $RETCODE
		elif [ "$RETCODE" -eq 132 ] ; then
			notify-send "(RDP) Dein Passwort wurde abgelehnt." "Entweder hast du dich vertippt oder du hast keinen Zugang."
			DO_RETRY="y"
		elif [ "$RETCODE" -eq 143 ] && grep -qF "Certificate verification failure 'self-signed certificate (18)' at stack position 0" "$LOGFILE" ; then
			if [ "$RETRY_WITH_TOFU" ] ; then
				set -- "$@" /cert:tofu
				RETRY_WITH_TOFU=""
				DO_RETRY="keep-password"
				notify-send "(RDP) Dem Server wird aufgrund des Trust-on-First-Use Verfahrens vertraut."
			else
				notify-send "(RDP) Dem Server kann nicht vertraut werden, bitte kontaktiere die IT!"
			fi
		fi
	done
	case "$RETCODE" in
		0|11|12)
			notify-send "(RDP) Verbindung beendet" "Die Verbindung zu $APPNAME wurde beendet."
			rm "$LOGFILE"
			exit 0 ;;
		*)
			notify-send  "(RDP) Verbindungsfehler zu $APPNAME" "Die Verbindung zu $APPNAME wurde aufgrund eines Fehlers beendet. $(get_error_message_for_code "$RETCODE")"
			;;
	esac
	exit "$RETCODE"
fi
