admin2.cgi 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. #!/usr/bin/haserl --shell=/bin/bash --upload-limit=32768 --upload-dir=/www/tmp
  2. <%# upload limit: 32Mb %>
  3. <%
  4. _WWW='/www'
  5. _PWDFILE="/opt/lib/htpasswd"
  6. _TMP="${_WWW}/tmp"
  7. _LOG="${_WWW}/log/admin.log"
  8. _DEBUG=1
  9. err() {
  10. _ERR="$?"
  11. [[ "$_ERR" -gt 0 ]] || return 0
  12. log "$1"
  13. head "${2:='400'}"
  14. exit "$_ERR"
  15. }
  16. logThis() {
  17. [[ "$_DEBUG" -gt 0 ]] || return 0
  18. local _TYPE='I:'
  19. [[ "$_ERR" -gt 0 ]] && _TYPE='E:'
  20. local _TIME; printf -v _TIME '%(%d.%m.%Y %H:%M:%S)T' -1
  21. printf '%b\n' "$_TIME $_TYPE ${@} " >> "$_LOG"
  22. [[ "$_DEBUG" -gt 1 ]] && printf '%b\n' "[verbose] $_TYPE ${1}"
  23. }
  24. headerPrint() {
  25. case "$1" in
  26. 200|'') printf '%b' 'HTTP/1.1 200 OK\r\n';;
  27. 301) printf '%b' "HTTP/1.1 301 Moved Permanently\r\nLocation: $HTTP_REFERER\r\n";;
  28. 403) printf '%b' 'HTTP/1.1 403 Forbidden\r\n';;
  29. 405) printf '%b' 'HTTP/1.1 405 Method Not Allowed\r\n';;
  30. 406) printf '%b' 'HTTP/1.1 406 Not Acceptable\r\n';;
  31. *) printf '%b' 'HTTP/1.1 400 Bad Request\r\n';;
  32. esac
  33. printf '%b' 'Content-Type: text/html\r\n\r\n';
  34. }
  35. htDigest() {
  36. _USER='admin'
  37. _PWD=$1
  38. _REALM='superglue'
  39. _HASH=$(echo -n "$_USER:$_REALM:$_PWD" | md5sum | cut -b -32)
  40. echo -n "$_USER:$_REALM:$_HASH"
  41. }
  42. setQueryVars() {
  43. env
  44. }
  45. getQueryFile() {
  46. local _UPLD="${HASERL_fwupload_path##*/}"
  47. logThis "'multipart': decoding stream"
  48. mv "$_TMP/$_UPLD" "$_TMP/fwupload.bin" 2>/dev/null || _ERR=$?
  49. if [[ $_ERR -gt 0 ]]; then
  50. showMesg 'Firmware upload has failed' 'Reboot your Superglue server and try again'
  51. fi
  52. }
  53. validIp() {
  54. local _IP=$1
  55. local _RET=1
  56. if [[ $_IP =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
  57. OIFS=$IFS
  58. IFS='.'
  59. _IP=($_IP)
  60. IFS=$OIFS
  61. [[ ${_IP[0]} -le 255 && ${_IP[1]} -le 255 && ${_IP[2]} -le 255 && ${_IP[3]} -le 255 ]]
  62. _RET=$?
  63. fi
  64. return $_RET
  65. }
  66. pwdChange() {
  67. if [[ ! -z "${_pwd##$_pwdd}" ]]; then
  68. _ERR=1
  69. showMesg 'Passwords did not match'
  70. fi
  71. if [[ ${#_pwd} -lt 6 ]]; then
  72. _ERR=1
  73. showMesg 'Password must be at least 6 characters long'
  74. fi
  75. runSuid "echo -e \"$_pwd\n$_pwd\" | passwd root"
  76. runSuid "echo $(htDigest $_pwd) > $_PWDFILE"
  77. _ERR=$?
  78. if [[ $_ERR -gt 0 ]]; then
  79. showMesg 'Password change failed'
  80. else
  81. showMesg 'Password is changed'
  82. fi
  83. }
  84. lanAddr() {
  85. logThis "new LAN addr is: $_laddr"
  86. validIp $_laddr || showMesg 'Not valid network address'
  87. doUci set laddr $_laddr
  88. _ERR=$?
  89. if [[ $_ERR -gt 0 ]]; then
  90. showMesg 'Setting network address failed'
  91. else
  92. (sleep 1; doUci commit network; doUci commit wireless;)&
  93. showMesg 'New network address is set' "Your server is now accessible under <a href='http://superglue.local/admin'>http://superglue.local/admin</a>"
  94. fi
  95. }
  96. wanSet() {
  97. if [[ ! -z $_wanifname ]]; then
  98. ## eth and wlan wan cases are different!
  99. ## eth wan requires:
  100. ## config interface 'wan'
  101. ## option ifname 'eth0'
  102. ##
  103. ## config wifi-iface
  104. ## option device 'radio0'
  105. ## option network 'wan'
  106. ## option disabled '1' (or no 'config wifi-iface' section at all)
  107. ##
  108. ## wlan wan requires:
  109. ## config interface 'wan'
  110. ## option proto 'dhcp'
  111. ## (without 'option ifname' specified!)
  112. ##
  113. ## config wifi-iface
  114. ## option device 'radio0'
  115. ## option network 'wan'
  116. logThis "wan.ifname=$_wanifname"
  117. if [[ $_wanifname == 'eth0' ]]; then
  118. doUci set wanifname $_wanifname
  119. doUci set wanwifacedis '1'
  120. elif [[ $_wanifname == 'wlan1' ]]; then
  121. doUci set wanifname ''
  122. doUci set wanwifacedis ''
  123. fi
  124. if [[ $_wanproto == 'dhcp' ]]; then
  125. doUci set wanproto dhcp
  126. elif [[ $_wanproto == 'static' ]]; then
  127. logThis "wan.ipaddr=$_wanipaddr"
  128. doUci set wanproto static
  129. doUci set wanipaddr $_wanipaddr
  130. doUci set wannetmask $_wannetmask
  131. fi
  132. if [[ $_wanifname == 'wlan1' ]]; then
  133. ssidChange || showMesg 'Wireless changes failed'
  134. fi
  135. ## background the following
  136. doUci commit network &&
  137. showMesg 'Internet connection is configured' 'Waiting for device to get ready' ||
  138. showMesg 'Configuring Internet connection failed'
  139. fi
  140. logThis "new WAN iface is: $_wanifname"
  141. }
  142. ssidChange() {
  143. ## check for iface
  144. [[ ! $_iface =~ ^('wan'|'lan')$ ]] && showMesg 'Error changing wireless settings' 'unknown/unconfigured interface'
  145. logThis "$_iface is being set"
  146. _p=$_iface
  147. ## default enc for now
  148. local _enc='psk2'
  149. if [[ $_iface == 'wan' ]]; then
  150. local _mode='sta'
  151. local _ssid="${_wanssid}"
  152. local _key="${_wankey}"
  153. else
  154. local _mode='ap'
  155. local _ssid="${_lanssid}"
  156. local _key="${_lankey}"
  157. fi
  158. logThis "ssid: $_ssid [$_mode], key: $_key [$_enc]"
  159. logThis $_wanssid
  160. if [[ ${#_ssid} -lt 4 ]]; then
  161. _ERR=1
  162. showMesg 'SSID must be at least 4 characters long'
  163. fi
  164. doUci set $_p'ssid' "${_ssid}"
  165. _ERR=$?
  166. [[ $_ERR -gt 0 ]] && showMesg 'New SSID is not set'
  167. if [[ -z $_key ]]; then
  168. ## if key is empty set encryption to none and remove key
  169. doUci set $_p'key' && doUci set $_p'enc' 'none'
  170. _ERR=$?
  171. else
  172. if [[ ${#_key} -lt 8 ]]; then
  173. _ERR=1
  174. showMesg 'Passphrase must be at least 8 characters long'
  175. fi
  176. doUci set $_p'key' "${_key}" && doUci set $_p'enc' "${_enc}"
  177. _ERR=$?
  178. [[ $_ERR -gt 0 ]] && showMesg 'Passphrase is not set'
  179. fi
  180. [[ $_ERR -gt 0 ]] && return $_ERR ##showMesg 'Wireless changes failed'
  181. doUci commit wireless ##&& showMesg 'Wireless changes applied'
  182. }
  183. #showError() {
  184. # headerPrint 406
  185. # logThis "$@"
  186. # echo "ERROR: $@"
  187. # exit 1
  188. #}
  189. showMesg() {
  190. logThis "$@"
  191. local _MSG=$1
  192. local _SUBMSG=$2
  193. _MSG=${_MSG:='Not defined'}
  194. _SUBMSG=${_SUBMSG:='back to control panel in a second..'}
  195. if [[ $_ERR -gt 0 ]]; then
  196. local _TYPE='ERROR: '
  197. headerPrint 406
  198. else
  199. local _TYPE='OK: '
  200. headerPrint 200
  201. fi
  202. htmlHead "<meta http-equiv='refresh' content='3;url=${HTTP_REFERER}'>"
  203. echo "<body>
  204. <h1>SG</h1>
  205. <hr>
  206. <h2 style='display:inline'>$_TYPE $_MSG</h2>
  207. <span style='display:inline; margin-left: 50px;'>$_SUBMSG</span>
  208. <hr>
  209. </body></html>"
  210. exit 0
  211. }
  212. updateFw() {
  213. logThis "updating fw"
  214. _FWFILE="${_TMP}/fwupload.bin"
  215. logThis "fwfile is: $(ls -lad $_FWFILE)"
  216. _OUT="$(/sbin/sysupgrade -T $_FWFILE 2>&1)"
  217. _ERR=$?
  218. [[ $_ERR -gt 0 ]] && showMesg "$_OUT"
  219. # _OUT="$(runSuid /sbin/mtd -e firmware -q write $_FWFILE firmware)"
  220. _ERR=$?
  221. [[ $_ERR -gt 0 ]] && showMesg "mtd failed, $_OUT"
  222. # runSuid reboot
  223. showMesg 'Firmware update is completed, rebooting..' 'this might take up to 60 seconds'
  224. }
  225. rebootNow() {
  226. logThis "reboot: now!"
  227. runSuid reboot
  228. showMesg 'Rebooting..' 'this might take up to 60 seconds'
  229. }
  230. doUci() {
  231. local _CMD=''
  232. local _ARG=''
  233. case $1 in
  234. get|set|commit) _CMD=$1;;
  235. *) logThis 'bad UCI command'; headerPrint 405; echo 'bad UCI command'; exit 1 ;;
  236. esac
  237. case $2 in
  238. lanssid) _ARG='wireless.@wifi-iface[0].ssid';;
  239. lanenc) _ARG='wireless.@wifi-iface[0].encryption';;
  240. lankey) _ARG='wireless.@wifi-iface[0].key';;
  241. lanipaddr) _ARG='network.lan.ipaddr';;
  242. wanifname) _ARG='network.wan.ifname';;
  243. wanproto) _ARG='network.wan.proto';;
  244. wanipaddr) _ARG='network.wan.ipaddr';;
  245. wannetmask) _ARG='network.wan.netmask';;
  246. wanwifacedis) _ARG='wireless.@wifi-iface[1].disabled';;
  247. wanssid) _ARG='wireless.@wifi-iface[1].ssid';;
  248. wanenc) _ARG='wireless.@wifi-iface[1].encryption';;
  249. wankey) _ARG='wireless.@wifi-iface[1].key';;
  250. *) if [[ $_CMD == 'commit' ]]; then
  251. _ARG=$2
  252. else
  253. logThis "bad UCI entry: $2"
  254. _ERR=1
  255. showMesg 'bad UCI entry'
  256. fi ;;
  257. esac
  258. if [[ $_CMD == 'get' ]]; then
  259. if [ ! -z $_ARG ]; then
  260. /sbin/uci -q get $_ARG || return $?
  261. fi
  262. fi
  263. if [[ $_CMD == 'set' ]]; then
  264. local _VAL=$3
  265. if [ -z $_VAL ]; then
  266. logThis "empty $_ARG value, removing record"
  267. runSuid /sbin/uci delete $_ARG || ( echo "uci delete $_ARG: error"; exit 1; )
  268. fi
  269. if [ ! -z $_ARG ]; then
  270. logThis "setting $_ARG value"
  271. runSuid /sbin/uci set $_ARG=$_VAL || ( echo "uci set $_ARG: error"; exit 1; )
  272. fi
  273. fi
  274. if [[ $_CMD == 'commit' ]]; then
  275. runSuid /sbin/uci commit $_ARG|| echo "uci commit $_ARG: error"
  276. if [[ "$_ARG" == 'wireless' ]]; then
  277. runSuid /sbin/wifi || echo 'wifi: error'
  278. fi
  279. if [[ "$_ARG" == 'network' ]]; then
  280. runSuid /etc/init.d/dnsmasq restart && runSuid /etc/init.d/network restart || echo 'network: error'
  281. fi
  282. fi
  283. }
  284. getStat() {
  285. . /usr/share/libubox/jshn.sh
  286. local _IFACE=$1
  287. local _IFSTAT=$(runSuid ubus call network.interface.wan status 2>/dev/null)
  288. logThis "$_IFSTAT"
  289. json_get_type _IFSTAT ipv4_address
  290. if json_get_type _IFSTAT ipv4_address && [[ "$_IFSTAT" == 'array' ]]; then
  291. json_select ipv4_address
  292. json_get_type _IFSTAT 1
  293. if [[ "$_IFSTAT" == 'object' ]]; then
  294. json_select 1
  295. json_get_var IP4 address
  296. json_get_var Subnet4 mask
  297. [[ "$IP4" != '' ]] && [[ "$Subnet4" != '' ]] && IP4="$IP4/$Subnet4"
  298. fi
  299. fi
  300. logThis $IP4
  301. }
  302. htmlHead() {
  303. echo "<!-- obnoxious code below, keep your ports tight -->
  304. <!doctype html>
  305. <html>
  306. <head><title>SuperGlue | Administration</title>
  307. $@
  308. <link rel='stylesheet' type='text/css' href='http://${HTTP_HOST}/resources/admin/admin.css'>
  309. </head>"
  310. }
  311. %>
  312. <% headerPrint '200' %>
  313. <%
  314. ## html head
  315. htmlHead
  316. sgver=$(cat /etc/superglue_version)
  317. devmod=$(cat /etc/superglue_model)
  318. openwrt=$(cat /etc/openwrt_version)
  319. wanifname=$(doUci get wanifname || echo 'wlan0') ## TODO fix this
  320. wanproto=$(doUci get wanproto)
  321. wanipaddr=$(doUci get wanipaddr)
  322. wannetmask=$(doUci get wannetmask)
  323. wanssid=$(doUci get wanssid)
  324. wankey=$(doUci get wankey)
  325. echo "<body>
  326. <h1>SG</h1>
  327. <hr>
  328. <h2 style='display:inline'>Superglue server control panel</h2>
  329. <span style='display:block;'>System version: $sgver | Device: $devmod | OpenWRT: $openwrt</span>
  330. <span style='display:block;'>$(uptime)</span>
  331. <hr>
  332. Update firmware:
  333. <form method='post' action='/admin/updatefw' enctype='multipart/form-data'>
  334. <div id='uploadbox'>
  335. <input id='uploadfile' placeholder='Choose file' disabled='disabled'>
  336. <input id='uploadbtn' name='fwupload' type='file'>
  337. </div>
  338. <input type='submit' value='Upload'>
  339. </form>
  340. <hr>
  341. Internet connection:
  342. <form method='post' action='/admin/wan' name='wan' onchange='formChange();'>
  343. <div style='display:inline-flex'>
  344. <div style='display:inline-block;'>
  345. <select name='wanifname' id='wanifname' style='display:block'>
  346. <option value='eth0' id='eth' $([[ $wanifname =~ ('eth') ]] && echo 'selected')>Wired (WAN port)</option>
  347. <option value='wlan1' id='wlan' $([[ $wanifname =~ ('wlan') ]] && echo 'selected')>Wireless (Wi-Fi)</option>
  348. </select>
  349. <fieldset id='wanwifi' class='hide'>
  350. <input type='text' name='wanssid' value='$wanssid'>
  351. <input type='password' name='wankey' value='$wankey'>
  352. </fieldset>
  353. </div>
  354. <div style='display:inline-block;'>
  355. <select name='wanproto' id='wanproto' style='display:block'>
  356. <option value='dhcp' name='dhcp' id='dhcp' $([[ $wanproto == 'dhcp' ]] && echo 'selected')>Automatic (DHCP)</option>
  357. <option value='stat' name='dhcp' id='stat' $([[ $wanproto == 'static' ]] && echo 'selected')>Manual (Static IP)</option>
  358. </select>
  359. <fieldset id='wanaddr' class='hide' >
  360. <input type='text' name='wanipaddr' id='wanipaddr' value='$wanipaddr'>
  361. <input type='text' name='wangw' id='wannetmask' value='$wannetmask'>
  362. </fieldset>
  363. </div>
  364. </div>
  365. <input type='hidden' name='iface' value='wan' class='inline'>
  366. <input type='submit' value='Apply'>
  367. </form>
  368. <hr>
  369. Local wireless network:
  370. <form method='post' action='/admin/ssidchange'>
  371. <div style='display:inline-flex'>
  372. <div style='display:inline-block;'>
  373. <input type='text' name='lanssid' value='$(doUci get lanssid)'>
  374. <input type='password' name='lankey' value='$(doUci get lankey)'>
  375. </div>
  376. <div style='display:inline-block;'>
  377. <input type='text' name='lanipaddr' value='$(doUci get lanipaddr)'>
  378. <input type='hidden' name='iface' value='lan' class='inline'>
  379. </div>
  380. </div>
  381. <input type='submit' value='Apply'>
  382. </form>
  383. <hr>
  384. <form action='/admin/rebootnow' method='post' class='inline'>
  385. <input type='hidden' name='reboot' value='now' class='inline'>
  386. <input type='submit' value='Reboot' class='inline'>
  387. </form>
  388. <form action='http://logout@${HTTP_HOST}/admin' method='get' class='inline'>
  389. <input type='submit' value='Logout' class='inline'>
  390. </form>
  391. <hr>
  392. Memory:
  393. <pre>$(free)</pre>
  394. <hr>
  395. Storage:
  396. <pre>$(df -h)</pre>
  397. <hr>
  398. Environment:
  399. <pre>$(env)</pre>
  400. <hr>
  401. </body>
  402. <script type='text/javascript' src='http://${HTTP_HOST}/resources/admin/admin.js'></script>
  403. </html>"
  404. %>