Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
executable file 445 lines (342 sloc) 12.057 kb
#!/bin/bash
####################################################################
# Prey Core Basic Functions - by Tomas Pollak (bootlog.org)
# URL: http://preyproject.com
# License: GPLv3
####################################################################
log(){
eval echo -e '"$1"' "$log_output"
}
####################################################################
# xml parsing functions
####################################################################
get_key(){
echo "$1" | sed -e 's/.*\/\(.*\)>/\1/' -e 'y/-/_/' # we also replace -'s to _'s
}
get_value(){
echo "$1" | sed 's/.*>\([^<].*\)<.*/\1/'
}
# expects attr name, returns value
# example: get_attribute 'name' $line
get_attribute(){
echo "$2" | sed "s/.*$1=\"\([^\"]*\)\".*/\1/"
# echo "$2" | sed -e "s/.*$1=\([a-z_\"']*\).*/\1/" -e "s/[^a-z_]//g"
}
####################################################################
# setting configs
####################################################################
# key, value
set_config(){
if [ -n "$1" ] && [ -n "$2" ]; then
local clean_key=$(echo "$1" | sed "s/^[0-9]/_/;s/[^a-zA-Z0-9_]/_/g")
local clean_val=$(printf "%q" "$2")
eval "${clean_key}=${clean_val}"
fi
}
# module, key, value
set_module_config(){
set_config "${1}__${2}" "$3"
}
save_config_value(){
local key="$1"
local val="$2"
if [ "$val" == "true" ]; then
local val='y'
elif [ "$val" == 'false' ]; then
local val='n'
fi
# use % as delimiter instead of / so URLs get set correctly
sed -i.backup -e "s%^$key=.*%$key='$val'%" "$config_file" 2> /dev/null
local rs=$?
if [ -f "$config_file" ]; then
rm -f "$config_file.backup" 2> /dev/null
else
mv "$config_file.backup" "$config_file" 2> /dev/null
fi
return $rs
}
####################################################################
# local var storage
####################################################################
# fetches a var and then assigns it as $value
# expects the name of hash and then the name of var
get_var(){
HASH="$1[*]"
local ${!HASH}
eval 'echo ${'"${2}"'}'
}
store_var(){
eval $1[\${#$1[*]}]="$2"
}
store_key_value(){
store_var "$1" "$2=\"$3\""
}
# if you need to fetch a specific trace or file
get_trace(){
get_var traces ${1}__$2
}
get_file(){
get_var files ${1}__$2
}
####################################################################
# list generators for report
####################################################################
separator='########################################################'
generate_query_string(){
local default_prefix="\n -F "
[ -n "$2" ] && prefix="$2" || prefix="$default_prefix"
for t in $(eval echo \${$1[@]}); do
local start=$(echo ${t%%=*})
local index=$(echo $(( ${#start} + 1 )))
if [ "$prefix" != "$default_prefix" ]; then
local trace_field=`echo "$start" | sed "s/^\([^_].*\)__\(.*\)/[\1][\2]/"`
else
local trace_field=`echo "$start" | sed 's/^\([^_].*\)__\(.*\)/\1[\2]/'`
fi
echo -n "${prefix}${trace_field}=${t:index}"
done
}
generate_list(){
for t in $(eval echo \${$1[@]}); do
local current_node=$(echo $t | sed 's/__.*//')
[ "$current_node" != "$previous_node" ] && echo -e "$separator\n# $current_node\n$separator\n"
# removes module name and replaces _'s with whitespaces
echo -e "$t\n" | sed -e 's/^\([^_].*\)__/ :: /' -e 's/%20/ /g' -e 's/_/ /'
local previous_node=$current_node
done
}
####################################################################
# trace & file functions
####################################################################
add_trace(){
log " ++ Adding trace for $current_module: $1"
store_key_value 'traces' "${current_module}__$1" "$(urlencode "$2")"
}
remove_traces(){
unset -v traces
log " -- Dropping all traces!"
}
add_file(){
if [ -f "$2" ]; then
log " ++ Adding file for $current_module: $1 -> $2"
store_key_value 'files' "${current_module}__$1" "$2"
else
log " ${red}!!${color_end} Couldn't find file at $2!"
fi
}
list_files(){
# log " -- ${#files[*]} files gathered!"
for f in "${files[@]}"; do
if [ "$post_method" == 'http' ]; then
# echo -e "-F $f" | sed -e 's/=/=@/'
echo "-F $f" | sed 's/^\([^_].*\)__\([^=].*\)=\(.*\)/\1[\2]=@\3/'
else # just list the file paths
echo $f | sed 's/^.*=\(.*\)/\1/'
fi
done
}
remove_files(){
for f in "${files[@]}"; do
file=`echo $f | sed 's/^.*=\(.*\)/\1/'`
rm -f "$file"
log " -- Removed $file"
done
unset -v files
}
####################################################################
# delay functions, mac and linux
####################################################################
# echoes random number between 1 and $1 (first argument passed)
get_random_number(){
echo $[ ( $RANDOM % $1 ) + 1 ]
}
# returns 1 if cron entry is set to one our intervals
one_hour_interval(){
echo "$current_delay" | grep "/" > /dev/null || echo 1
}
# returns cron delay depending on device's state:
# when missing, every X minutes, otherwise every hour on minute X
get_delay_for(){
echo '*/'$1' * * * *'
}
get_random_minute_delay(){
local min=$(get_random_number 59)
echo "${min} * * * *"
}
get_current_delay(){
# crontab -l | grep prey | sed "s/^..\([0-9]*\).*/\1/"
crontab -l 2> /dev/null | grep prey | head -1 | sed 's/ \/.*//'
}
update_execution_delay(){
local full_path=$(full_path "$base_path")
(crontab -l 2> /dev/null | grep -v prey; echo "${1}" "${full_path}/prey.sh > /var/log/prey.log 2>&1") | crontab -
}
# if device is missing we'll make sure the current delay matches the one
# on the server. otherwise we'll make sure it is set to the regular interval.
check_and_update_delay(){
local current_delay=$(get_current_delay)
# if trigger is loaded and device not missing, set to one hour intervals
if [[ -n "$current_delay" && -n "$(is_trigger_loaded)" && -z "$device_missing" ]]; then
# if already set to one hour interval, return
[ -n "$(one_hour_interval)" ] && return 0
local new_delay=$(get_random_minute_delay)
log " -- Setting delay to regular interval."
else
local new_delay=$(get_delay_for "$1")
# if interval hasn't changed, return
[ "$current_delay" == "$new_delay" ] && return 0
log " -- Setting frequency to $1!"
fi
update_execution_delay "$new_delay"
}
#ensure_trigger_loaded(){
# [ -z "$(is_trigger_loaded)" ] && reload_trigger
#}
running_from_cron(){
# tty -s
# [ $? -eq 1 ] && echo 1
[ "$TERM" == "dumb" ] && echo 1
}
####################################################################
# http functions
####################################################################
# if try_proxy does not contain a dot (e.g. 'true' or something else)
# then lets make sure we use a valid proxy.
get_proxy_server(){
[ -n "$try_proxy" ] && echo "$try_proxy" || get_system_proxy
}
send_request(){
local url="$1"
local curl_arguments="$2"
local proxy_to_use="$3"
local headers_file="$tmpbase/prey-curl-headers-${RANDOM}.txt"
if [ -n "$proxy_to_use" ]; then
log " -- Trying via proxy: ${proxy_to_use}..."
curl_arguments="$curl_arguments -x $proxy_to_use"
fi
response_body=""
response_headers=""
response_body=$(getter $curl_arguments -L $url --dump-header "$headers_file" -S --stderr -)
local rs=$?
if [[ $rs -eq 0 && -f "$headers_file" ]]; then
response_headers=$(cat "$headers_file" && rm -f "$headers_file" 2> /dev/null)
get_status_code
elif [ $rs -eq 127 ]; then
log " -- Hold on. The curl binary is no longer in place!"
elif [ -z "$proxy_to_use" ]; then
if [ -z "$proxy_checked" ]; then
proxy_server=$(get_proxy_server)
proxy_checked=1
fi
if [ -n "$proxy_server" ]; then
send_request "$url" "$curl_arguments" "$proxy_server"
else
log_response_error "$url"
fi
else # tried proxy to no avail.
# it may be possible that the proxy does not support SSL,
# so we can try switching to plain HTTP as a last resort
if [ -n "$(find_in "$url" 'https:')" ]; then
local new_url=$(echo "$url" | sed 's/https:/http:/')
send_request "$new_url" "$curl_arguments" "$proxy_to_use"
else
log_response_error "$url" "$proxy_to_use"
fi
fi
}
get_status_code(){
# if we get a redirect response, we should capture the last http status code
response_status=$(echo -e "$response_headers" | grep 'HTTP/' | tail -1 | cut -d" " -f2)
}
# we may eventually use a specific header for Prey
get_header_value(){
echo "$response_headers" | grep -i "$1" | tail -1 | sed 's/.*: \([a-z\/-]*\).*/\1/'
}
# fetches last response if online actions were enabled for the device
get_last_response(){
response_body=$(cat "$last_response")
}
log_response_error(){
local url="$1"
local proxy_used="$2"
log "\n !! Got invalid response! This probably means there is a connection issue."
log " -- Please check your firewall settings, allowing Curl to connect to ${url} through port 80."
log " -- If you use a proxy server please check the try_proxy setting in the config file."
[ -n "$proxy_used" ] && log " -- Proxy server found: ${proxy_used}"
log " -- The response we got was: \n\n${response_headers}\n${response_body}\n"
# notify exception
local exception_message="HTTP Request Error: ${url}"
local exception_trace="$response_headers\n\n${response_body}"
if [ -n "$proxy_used" ]; then
exception_message="$exception_message (Using Proxy)"
fi
notify_exception "$exception_message" "$exception_trace"
}
####################################################################
# check mode functions
####################################################################
verify_installation(){
log " -- Checking if cron daemon is running..."
if [ -n $(is_process_running 'cron') ]; then
log " -- Cron daemon found."
else
log " !! Cron daemon not found! Try running it with 'sudo /etc/init.d/cron start'."
fi
log " -- Checking for crontab entry..."
local result=$(crontab -l | grep 'prey.sh' | wc -l 2> /dev/null)
if [ "$result" -gt 0 ]; then
log " -- Found!"
else
log " !! Not found!\n -> It seems Prey's crontab entry was removed after installation. Please set again the running interval."
fi
}
verify_smtp_settings(){
if [ "$mail_to" != "mailbox@domain.com" ]; then
log " -- Target mailbox set."
else
log " !! Target mailbox not set!"
fi
if [ "$smtp_username" != "username@gmail.com" ]; then
log " -- SMTP username set."
else
log " !! SMTP username not set!"
fi
if [ "$(decrypt $smtp_password)" != "" ]; then
log " -- Password seems to be fine as well."
else
log " !! Password not set! (Remember it should be base64 encrypted)."
fi
}
####################################################################
# self setup functions
####################################################################
get_hardware_info(){
initialize_module "system"
scan_system_hardware
full_hardware_params
}
self_setup(){
log ' -- Gathering system and hardware information...'
get_pc_info # sets pc_name and pc_type
local pc_hardware_params="$(get_hardware_info)"
log ' -- Sending request to Prey Control Panel...'
local os_name="$os"
[ "$os" == "linux" ] && [ -n "$distro_name" ] && os_name="$distro_name"
local params="device[title]=$(urlencode "$pc_name")&device[device_type]=$pc_type&device[os_version]=$os_version&device[os]=$(capitalize $os_name)${pc_hardware_params}"
send_request "$control_panel_url/devices.xml" "--connect-timeout 30 -u $api_key:x -d "$params""
log " -- Got response status ${response_status}."
device_key=$(echo "$response_body" | grep "<key>" | sed 's/.*<key>\(.*\)<\/key>.*/\1/')
if [ -n "$device_key" ]; then
log ' -- Device succesfully registered! Applying configuration...'
save_config_value device_key "$device_key"
if [ $? == 1 ]; then
log " -- There was a problem saving the configuration. You probably don't have permissions to modify $base_path/config."
else
log " -- All set. Assigned key is $device_key."
fi
else
notify_exception "self-setup failed with code: ${response_status}" "${params}"
log " -- Couldn't add this device to your account. Make sure you have available slots!\n"
exit 1
fi
}
Jump to Line
Something went wrong with that request. Please try again.