fritzmanager/freetz-manager.sh

168 lines
3.7 KiB
Bash
Executable File

#!/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 $@