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