sc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648
  1. #!/bin/sh
  2. #
  3. # $Id$
  4. #
  5. # sc: ser control; tool for maintaining ser's databases
  6. #
  7. # ser's FIFO server
  8. SER_FIFO=/tmp/ser_fifo
  9. # period in which stats are reprinted
  10. WATCH_PERIOD=2
  11. # SQL config
  12. SQL_DB=ser
  13. SQL_HOST=localhost
  14. SQL_USER=ser
  15. # the read-only user for whom password may be stored here
  16. RO_USER=serro
  17. RO_PW=47serro11
  18. # binaries
  19. GENHA1='gen_ha1'
  20. MYSQL='mysql'
  21. SER='sr'
  22. # ACL name verification
  23. VERIFY_ACL=1
  24. ACL_GROUPS="local ld int voicemail free-pstn"
  25. # expiration time for alias table
  26. FOREVER='2020-05-28 21:32:15'
  27. FOREVER_REL=1073741823
  28. VERSION='$Revision$'
  29. #### SQL names
  30. # Usr Loc Table
  31. USRLOC=location
  32. USER_COLUMN=user
  33. CALLID_COLUMN=callid
  34. # subscriber table
  35. TABLE=subscriber
  36. REALM_COLUMN=realm
  37. HA1_COLUMN=HA1
  38. HA1B_COLUMN=HA1B
  39. PASSWORD_COLUMN=password
  40. SUBSCRIBER_COLUMN='user_id'
  41. EMAIL_COLUMN=email_address
  42. SUB_CREATED_COLUMN=datetime_created
  43. SUB_MODIFIED_COLUMN=datetime_modified
  44. PHP_LIB_COLUMN=phplib_id
  45. # acl table
  46. ACL_TABLE=grp
  47. ACL_USER_COLUMN=user
  48. ACL_GROUP_COLUMN=grp
  49. ACL_MODIFIED_COLUMN=last_modified
  50. # aliases table
  51. A_TABLE=aliases
  52. A_USER_COLUMN=user
  53. A_CONTACT_COLUMN=contact
  54. A_EXPIRES_COLUMN=expires
  55. A_Q_COLUMN=q
  56. A_CALLID_COLUMN=callid
  57. A_CSEQ_COLUMN=cseq
  58. A_LAST_MODIFIED_COLUMN=last_modified
  59. FIFO_DBG=0
  60. #===================================================================
  61. usage() {
  62. CMD=`basename $0`
  63. if [ "0$VERIFY_ACL" -eq 1 ] ; then
  64. EXTRA_TEXT="ACL privileges are: $ACL_GROUPS"
  65. fi
  66. cat <<EOF
  67. $0 $VERSION
  68. usage:
  69. * subscribers *
  70. $CMD add <username> <password> <email> .. add a new subscriber (*)
  71. $CMD passwd <username> <passwd> ......... change user's password (*)
  72. $CMD rm <username> ...................... delete a user (*)
  73. $CMD mail <username> .................... send an email to a user
  74. $CMD alias show [<alias>] ............... show aliases
  75. $CMD alias rm <alias> ................... remove an alias
  76. $CMD alias add <alias> <uri> ............ add an aliases
  77. * access control lists *
  78. $CMD acl show [<username>] .............. show user membership
  79. $CMD acl grant <username> <group> ....... grant user membership (*)
  80. $CMD acl revoke <username> [<group>] .... grant user membership(s) (*)
  81. * usrloc *
  82. $CMD ul show [<username>]................ show in-RAM online users
  83. $CMD ul rm <username> ................... delete user's UsrLoc entries
  84. $CMD ul add <username> <uri> ............ introduce a permanent UrLoc entry
  85. $CMD showdb [<username>] ................ show online users flushed in DB
  86. * server health *
  87. $CMD monitor ............................ show internal status
  88. $CMD ps ................................. show runnig processes
  89. $CMD fifo ............................... send raw commands to FIFO
  90. Commands labeled with (*) will prompt for a MySQL password.
  91. If the variable PW is set, the password will not be prompted.
  92. $EXTRA_TEXT
  93. EOF
  94. }
  95. # check the parameter if it is a valid SIP URI
  96. # quite simplified now -- it captures just very basic
  97. # errors
  98. check_uri() {
  99. echo "$1" | grep -E "^sip:([a-zA-Z0-9_]+@)?.*\..*"
  100. }
  101. #params: none
  102. # output: PW
  103. prompt_pw() {
  104. if [ -z "$PW" ] ; then
  105. read -s -p "MySql Password: " PW
  106. echo
  107. fi
  108. }
  109. # process output from FIFO server; if everything is ok
  110. # skip the first "ok" line and proceed to returned
  111. # parameters
  112. filter_fl()
  113. {
  114. # tail +2
  115. awk 'BEGIN {line=0;IGNORECASE=1;}
  116. {line++}
  117. line==1 && /^200 ok/ { next }
  118. { print }'
  119. }
  120. fifo_cmd()
  121. {
  122. if [ "0${FIFO_DBG}" -eq 1 ] ; then
  123. echo "entering fifo_cmd $*"
  124. fi
  125. if [ "$#" -lt 1 ]; then
  126. echo "ERROR: fifo_cmd must take at least command name as parameter"
  127. exit
  128. fi
  129. name=ser_receiver_$$
  130. path=/tmp/$name
  131. if [ ! -w $SER_FIFO ]; then
  132. echo "Error opening ser's FIFO $SER_FIFO"
  133. echo "Make sure you have line fifo=$SER_FIFO in your config"
  134. exit 1
  135. fi
  136. mkfifo $path
  137. if [ $? -ne 0 ] ; then
  138. echo "error opening read fifo $path"
  139. exit 1
  140. fi
  141. chmod a+w $path
  142. # construct the command now
  143. CMD=":$1:$name\n";
  144. shift
  145. while [ -n "$1" ] ; do
  146. CMD="${CMD}${1}\n"
  147. shift
  148. done
  149. CMD="${CMD}\n"
  150. # start reader now so that it is ready for replies
  151. # immediately after a request was sent out
  152. cat < $path | filter_fl &
  153. # issue FIFO request (printf taken to deal with \n)
  154. printf "$CMD" > $SER_FIFO
  155. # wait for the reader to complete
  156. wait
  157. rm $path
  158. if [ "0${FIFO_DBG}" -eq 1 ] ; then
  159. printf "FIFO command was:\n$CMD"
  160. fi
  161. }
  162. # $1 = name $2=path $3=attempt
  163. print_stats() {
  164. echo "[cycle #: $3; if constant make sure server lives and fifo is on]"
  165. cat < $2 | filter_fl &
  166. cat > $SER_FIFO <<EOF
  167. :version:$1
  168. EOF
  169. wait
  170. cat < $2 | filter_fl &
  171. cat > $SER_FIFO << EOF
  172. :uptime:$1
  173. EOF
  174. wait
  175. echo
  176. echo Transaction Statistics
  177. cat < $2 | filter_fl &
  178. cat > $SER_FIFO <<EOF
  179. :t_stats:$1
  180. EOF
  181. wait
  182. echo
  183. echo Stateless Server Statistics
  184. cat < $2 | filter_fl &
  185. cat > $SER_FIFO <<EOF
  186. :sl_stats:$1
  187. EOF
  188. wait
  189. echo
  190. echo UsrLoc Stats
  191. cat < $2 | filter_fl &
  192. cat > $SER_FIFO <<EOF
  193. :ul_stats:$1
  194. EOF
  195. wait
  196. }
  197. # input: sql query, optional mysql command-line params
  198. sql_query() {
  199. # if password not yet queried, query it now
  200. if [ -z "$PW" ] ; then
  201. read -s -p "MySql Password: " PW >&2
  202. echo >&2
  203. fi
  204. $MYSQL $2 -h $SQL_HOST -u $SQL_USER "-p$PW" -e "$1 ;" $SQL_DB
  205. }
  206. # input: sql query, optional mysql command-line params
  207. sql_ro_query() {
  208. $MYSQL $2 -h $SQL_HOST -u $RO_USER "-p$RO_PW" \
  209. -e "$1 ;" $SQL_DB
  210. }
  211. usrloc() {
  212. if [ "$#" -lt 2 ] ; then
  213. echo "usrloc: too few parameters"
  214. exit 1
  215. fi
  216. if [ "$1" = "alias" ] ; then
  217. TABLE="$A_TABLE"
  218. elif [ "$1" = "ul" ] ; then
  219. TABLE="$USRLOC"
  220. else
  221. echo "usrloc: unknown table name"
  222. exit 1
  223. fi
  224. shift
  225. case $1 in
  226. show)
  227. if [ $# -eq 2 ] ; then
  228. fifo_cmd ul_show_contact $TABLE $2
  229. elif [ $# -eq 1 ] ; then
  230. fifo_cmd ul_dump
  231. else
  232. echo "wrong number of params for usrloc show"
  233. usage
  234. exit 1
  235. fi
  236. exit $?
  237. ;;
  238. add)
  239. if [ $# -ne 3 ] ; then
  240. usage
  241. exit 1
  242. fi
  243. shift
  244. check_uri "$2"
  245. if [ "$?" -ne "0" ] ; then
  246. echo "$2 is not a valid URI"
  247. exit 1
  248. fi
  249. fifo_cmd ul_add "$TABLE" "$1" "$2" "$FOREVER_REL" "1.00"
  250. exit $?
  251. ;;
  252. rm)
  253. if [ $# -ne 2 ] ; then
  254. usage
  255. exit 1
  256. fi
  257. shift
  258. fifo_cmd ul_rm $TABLE $1
  259. ;;
  260. *)
  261. usage
  262. exit 1
  263. ;;
  264. esac
  265. }
  266. acl() {
  267. case $1 in
  268. show)
  269. if [ $# -eq 2 ] ; then
  270. is_user $2
  271. if [ $? -ne 0 ] ; then
  272. echo non-existent user
  273. exit 1;
  274. fi
  275. CLAUSE=" WHERE $ACL_USER_COLUMN='$2' "
  276. elif [ $# -ne 1 ] ; then
  277. usage
  278. exit 1
  279. fi
  280. QUERY="select * FROM $ACL_TABLE $CLAUSE ; "
  281. sql_ro_query "$QUERY"
  282. ;;
  283. grant)
  284. if [ $# -lt 3 ] ; then
  285. usage
  286. exit 1
  287. fi
  288. prompt_pw
  289. is_user $2
  290. if [ $? -ne 0 ] ; then
  291. echo non-existent user
  292. exit 1
  293. fi
  294. SIP_USER="$2"
  295. shift 2
  296. while [ $# -gt 0 ] ; do
  297. if [ $VERIFY_ACL -eq 1 ] ; then
  298. found=0
  299. for i in $ACL_GROUPS ; do
  300. if [ "$1" = "$i" ] ; then
  301. found=1
  302. break
  303. fi
  304. done
  305. if [ $found -eq 0 ] ; then
  306. echo "Invalid privilege: $1 ignored"
  307. shift
  308. continue
  309. fi
  310. fi
  311. QUERY="insert into $ACL_TABLE \
  312. ($ACL_USER_COLUMN,$ACL_GROUP_COLUMN,$ACL_MODIFIED_COLUMN) \
  313. values ('$SIP_USER','$1', now());"
  314. sql_query "$QUERY"
  315. if [ $? -ne 0 ] ; then
  316. echo "SQL Error"
  317. exit 1
  318. fi
  319. shift
  320. done
  321. $0 acl show $SIP_USER
  322. ;;
  323. revoke)
  324. if [ $# -eq 3 ] ; then
  325. CLAUSE=" and $ACL_GROUP_COLUMN='$3' "
  326. elif [ $# -ne 2 ] ; then
  327. usage
  328. exit 1
  329. fi
  330. QUERY="delete from $ACL_TABLE where \
  331. $ACL_TABLE.$ACL_USER_COLUMN='$2' $CLAUSE"
  332. sql_query "$QUERY"
  333. $0 acl show $2
  334. ;;
  335. *)
  336. usage
  337. exit 1
  338. ;;
  339. esac
  340. }
  341. # params: user
  342. # output: false if exists, true otherwise
  343. is_user() {
  344. QUERY="select count(*) from $TABLE \
  345. where $SUBSCRIBER_COLUMN='$1' and $REALM_COLUMN='$SIP_DOMAIN';"
  346. CNT=`sql_ro_query "$QUERY" | grep -v ERROR | tail -n1`
  347. if [ "0$CNT" -eq 0 ] ; then
  348. false
  349. else
  350. true
  351. fi
  352. }
  353. # params: user, password
  354. # output: HA1, HA1B
  355. credentials()
  356. {
  357. HA1=`$GENHA1 $1 $SIP_DOMAIN $2`
  358. if [ $? -ne 0 ] ; then
  359. echo "HA1 calculation failed"
  360. exit 1
  361. fi
  362. HA1B=`$GENHA1 "$1@$SIP_DOMAIN" $SIP_DOMAIN $2`
  363. if [ $? -ne 0 ] ; then
  364. echo "HA1B calculation failed"
  365. exit 1
  366. fi
  367. }
  368. #================================================================
  369. if [ -z "$SIP_DOMAIN" ] ; then
  370. echo "You need to set environment variable SIP_DOMAIN (e.g. to 'foobar.com') first"
  371. echo
  372. usage
  373. exit 1
  374. fi
  375. # if the script calls itself ...
  376. export PW
  377. case $1 in
  378. passwd)
  379. if [ $# -ne 3 ] ; then
  380. usage
  381. exit 1
  382. fi
  383. shift
  384. credentials $1 $2
  385. prompt_pw
  386. is_user $1
  387. if [ $? -ne 0 ] ; then
  388. echo non-existent user
  389. exit 1
  390. fi
  391. QUERY="update $TABLE \
  392. set $HA1_COLUMN='$HA1', $HA1B_COLUMN='$HA1B', $PASSWORD_COLUMN='$2' \
  393. , $SUB_MODIFIED_COLUMN=now() \
  394. WHERE $SUBSCRIBER_COLUMN='$1' and $REALM_COLUMN='$SIP_DOMAIN';"
  395. sql_query "$QUERY"
  396. if [ $? -ne 0 ] ; then
  397. echo "password change failed"
  398. else
  399. echo "password change succeeded"
  400. fi
  401. ;;
  402. add)
  403. if [ $# -ne 4 ] ; then
  404. usage
  405. exit 1
  406. fi
  407. shift
  408. credentials $1 $2
  409. prompt_pw
  410. is_user $1
  411. if [ $? -eq 0 ] ; then
  412. echo user already exists
  413. exit 1
  414. fi
  415. QUERY="insert into $TABLE \
  416. ($SUBSCRIBER_COLUMN,$REALM_COLUMN,$HA1_COLUMN,\
  417. $HA1B_COLUMN,$PASSWORD_COLUMN,$EMAIL_COLUMN, $SUB_CREATED_COLUMN, \
  418. $PHP_LIB_COLUMN ) \
  419. values ('$1','$SIP_DOMAIN','$HA1','$HA1B','$2', '$3', now(), '$HA1' );";
  420. sql_query "$QUERY"
  421. if [ $? -ne 0 ] ; then
  422. echo "introducing a new user to the database failed"
  423. else
  424. echo "new user added"
  425. fi
  426. ;;
  427. monitor|console|moni|con)
  428. name=ser_receiver_$$
  429. path=/tmp/$name
  430. if [ ! -w $SER_FIFO ]; then
  431. echo "Error opening ser's FIFO $SER_FIFO"
  432. echo "Make sure you have line fifo=$SER_FIFO in your config"
  433. exit 1
  434. fi
  435. mkfifo $path
  436. if [ $? -ne 0 ] ; then
  437. echo "error opening read fifo $path"
  438. exit 1
  439. fi
  440. trap "rm $path; clear; echo sc monitor ^C-ed; exit 1" 2
  441. attempt=0
  442. clear
  443. while [ 1 -eq 1 ]; do
  444. attempt=`expr $attempt + 1`
  445. #clear
  446. tput cup 0 0
  447. print_stats $name $path $attempt
  448. sleep $WATCH_PERIOD
  449. done
  450. rm $path
  451. exit 0
  452. ;;
  453. mail)
  454. if [ $# -ne 2 ] ; then
  455. usage
  456. exit 1
  457. fi
  458. shift
  459. QUERY="select $TABLE.$EMAIL_COLUMN from $TABLE where \
  460. $TABLE.$SUBSCRIBER_COLUMN='$1'"
  461. EA=`sql_ro_query "$QUERY" "-B" | grep -v ERROR | tail -n1`
  462. if [ $? -ne 0 ] ; then
  463. echo "MySql query failed"
  464. exit 1
  465. fi
  466. echo "Write email to $1: $EA now ..."
  467. mail -s "Message from $SIP_DOMAIN SIP admin" $EA
  468. if [ $? -eq 0 ] ; then
  469. echo message sent
  470. else
  471. echo sending message failed
  472. fi
  473. ;;
  474. alias|ul)
  475. usrloc "$@"
  476. ;;
  477. online)
  478. fifo_cmd ul_dump |grep aor| awk '{print $3}' | sort | sort -mu
  479. exit $?
  480. ;;
  481. showdb|userdb)
  482. if [ $# -eq 2 ] ; then
  483. is_user $2
  484. if [ $? -ne 0 ] ; then
  485. echo non-existent user
  486. exit 1;
  487. fi
  488. elif [ $# -ne 1 ] ; then
  489. usage
  490. exit 1
  491. fi
  492. shift
  493. QUERY1="select $TABLE.$EMAIL_COLUMN from $TABLE where \
  494. $TABLE.$SUBSCRIBER_COLUMN='$1'"
  495. QUERY2="select $USRLOC.* from $USRLOC where \
  496. $USRLOC.$USER_COLUMN='$1' order by expires desc"
  497. QUERY3="select $USRLOC.$USER_COLUMN, $TABLE.$EMAIL_COLUMN, $USRLOC.$CALLID_COLUMN \
  498. from $TABLE, $USRLOC where \
  499. $TABLE.$SUBSCRIBER_COLUMN=$USRLOC.$USER_COLUMN order by $USRLOC.$USER_COLUMN"
  500. if [ $# -eq 1 ] ; then
  501. sql_ro_query "$QUERY1"
  502. sql_ro_query "$QUERY2"
  503. else
  504. sql_ro_query "$QUERY3"
  505. fi
  506. echo -n "Note: Due to usage of cache, server's list "
  507. echo "may differ from DB list."
  508. ;;
  509. rm)
  510. if [ $# -ne 2 ] ; then
  511. usage
  512. exit 1
  513. fi
  514. shift
  515. prompt_pw
  516. is_user $1
  517. if [ $? -ne 0 ] ; then
  518. echo non-existent user
  519. exit 1
  520. fi
  521. QUERY="delete from $TABLE where $TABLE.$SUBSCRIBER_COLUMN='$1'"
  522. sql_query "$QUERY"
  523. $0 acl revoke $1 > /dev/null 2>&1
  524. $0 dul $1 > /dev/null 2>&1
  525. ;;
  526. ps)
  527. fifo_cmd ps
  528. ;;
  529. acl)
  530. shift
  531. acl "$@"
  532. ;;
  533. fifo)
  534. shift
  535. fifo_cmd "$@"
  536. ;;
  537. version)
  538. echo "$0 $VERSION"
  539. ;;
  540. *)
  541. usage
  542. exit 1
  543. ;;
  544. esac