commit b8026480c63739eb9dadc30570177d90efe23d9e Author: Alex Denes Date: Wed Jun 29 09:44:05 2022 +0000 Initial commit diff --git a/freetz-manager.sh b/freetz-manager.sh new file mode 100755 index 0000000..53ddef2 --- /dev/null +++ b/freetz-manager.sh @@ -0,0 +1,167 @@ +#!/bin/sh + +# Freetz! Web manager +# caskd +# CC0 + +: ${FB_ENDPOINT:-'192.168.178.1'} +: ${FB_CONFIG_PASS:-'defaultpassword'} + +main() { + for i in curl iconv md5sum cut xmlstarlet; do + which "$i" >/dev/null || log_error "Missing dependency: $i" + done + + log_info "Creating session" + FB_SESSION="$(fb_auth)" + if [ -z "$FB_SESSION" ]; then + return "$?" + fi + + for arg in $@; do + case "$arg" in + export|import) eval fb_"$arg" || return "$?";; + *) ret="$?"; log_error "Invalid command $arg"; return "$ret";; + esac + done +} + +log_error() { + printf '%s\n' "$1" >&2 +} + +log_info() { + printf '%s\n' "$1" >&2 +} + +fb_auth() { + local \ + fb_endpoint="$FB_ENDPOINT" \ + fb_username="$FB_USERNAME" \ + fb_password="$FB_PASSWORD" + + if [ -z "$fb_password" ]; then + log_error "Missing login password" + return 1 + fi + + log_info "Fetching login info from $fb_endpoint" + local login_data="$( \ + if ! curl -sSLf "http://$fb_endpoint/login_sid.lua"; then + ret="$?" + log_error "Failed to fetch login data" + return "$ret" + fi + )" + + local auth_challange="$( \ + printf '%s' "$login_data" | \ + xmlstarlet sel -t -v '/SessionInfo/Challenge' \ + )" + + if [ -z "$auth_challange" ]; then + log_error "Got empty challange back" + return 1 + fi + + # If no user is given, pick the user that was last used + if [ -z "$fb_username" ]; then + local fb_username="$( \ + printf '%s' "$login_data" | \ + xmlstarlet sel -t -v '/SessionInfo/Users//User[@last=1]' \ + )" + + # If no user authenticated, pick the first user + if [ -z "$fb_username" ]; then + local fb_username="$( \ + printf '%s' "$login_data" | \ + xmlstarlet sel -t -v '/SessionInfo/Users//User[1]' \ + )" + fi + + if [ -z "$fb_username" ]; then + log_error "Failed to autodetect username" + return 1 + else + log_info "No username given, picking '$fb_username'" + fi + fi + + log_info "Got challange $auth_challange" + local hashed="$( \ + printf '%s' "$auth_challange-$fb_password" | \ + iconv -f ISO8859-1 -t UTF-16LE | \ + md5sum -b | \ + cut -d' ' -f1)" + + local response="$auth_challange-$hashed" + + log_info "Sending challange response $response" + local session_id="$( \ + curl -sSLf "http://$fb_endpoint/login_sid.lua" \ + --data-urlencode "username=$fb_username" \ + --data-urlencode "response=$response" | \ + xmlstarlet sel -t -v '/SessionInfo/SID' \ + )" + + if [ "$session_id" == "0000000000000000" ]; then + log_error "Failed to log in" + return 1 + fi + + printf '%s' "$session_id" + log_info "Authenticated" +} + +fb_export() { + local \ + fb_endpoint="$FB_ENDPOINT" \ + fb_session="$FB_SESSION" \ + fb_config_pass="$FB_CONFIG_PASS" + + log_info "Exporting configuration of $fb_endpoint" + if ! curl -\# -Lf "http://$fb_endpoint/cgi-bin/firmwarecfg" \ + -X POST \ + --form-string sid="$fb_session" \ + --form-string ImportExportPassword="$fb_config_pass" \ + --form-string ConfigExport='' + then + ret="$?" + log_error "Failed to export configuration" + return "$ret" + fi +} + +fb_import() { + local \ + fb_endpoint="$FB_ENDPOINT" \ + fb_session="$FB_SESSION" \ + fb_config_pass="$FB_CONFIG_PASS" + + log_info "Telling Fritz! Box to load the entire configuration" + if ! curl -sSLf "http://$fb_endpoint/data.lua" \ + -X POST \ + --form-string sid="$fb_session" \ + --form-string ImportExportPassword="$fb_config_pass" \ + --form-string cfgtakeover='all' \ + --form-string restore='' >/dev/null + then + ret="$?" + log_error "Failed to set configuration restore options" + return "$ret" + fi + + log_info "Uploading configuration via STDIN" + if ! curl -\# -Lf "http://$fb_endpoint/cgi-bin/firmwarecfg" \ + -X POST \ + --form-string sid="$fb_session" \ + --form-string ImportExportPassword="$fb_config_pass" \ + -F ConfigImportFile="@-;filename=config.cfg;type=application/octet-stream" >/dev/null + then + ret="$?" + log_error "Failed to upload configuration" + return "$ret" + fi +} + +main $@