summaryrefslogtreecommitdiff
path: root/src/monkeysphere-server
blob: 69395a4dbb449f4b6dee8e85455586aa955d7e7d (plain)
  1. #!/bin/bash
  2. # monkeysphere-server: MonkeySphere server admin tool
  3. #
  4. # The monkeysphere scripts are written by:
  5. # Jameson Rollins <jrollins@fifthhorseman.net>
  6. #
  7. # They are Copyright 2008, and are all released under the GPL, version 3
  8. # or later.
  9. ########################################################################
  10. PGRM=$(basename $0)
  11. SHARE=${MONKEYSPHERE_SHARE:="/usr/share/monkeysphere"}
  12. export SHARE
  13. . "${SHARE}/common" || exit 1
  14. VARLIB="/var/lib/monkeysphere"
  15. export VARLIB
  16. # date in UTF format if needed
  17. DATE=$(date -u '+%FT%T')
  18. # unset some environment variables that could screw things up
  19. unset GREP_OPTIONS
  20. # default return code
  21. RETURN=0
  22. ########################################################################
  23. # FUNCTIONS
  24. ########################################################################
  25. usage() {
  26. cat <<EOF
  27. usage: $PGRM <subcommand> [options] [args]
  28. MonkeySphere server admin tool.
  29. subcommands:
  30. update-users (u) [USER]... update user authorized_keys files
  31. gen-key (g) [NAME[:PORT]] generate gpg key for the server
  32. -l|--length BITS key length in bits (2048)
  33. -e|--expire EXPIRE date to expire
  34. -r|--revoker FINGERPRINT add a revoker
  35. add-hostname (n+) NAME[:PORT] add hostname user ID to server key
  36. revoke-hostname (n-) NAME[:PORT] revoke hostname user ID
  37. show-key (s) output all server host key information
  38. fingerprint (f) output just the key fingerprint
  39. publish-key (p) publish server host key to keyserver
  40. diagnostics (d) report on server monkeysphere status
  41. add-id-certifier (c+) KEYID import and tsign a certification key
  42. -n|--domain DOMAIN limit ID certifications to DOMAIN
  43. -t|--trust TRUST trust level of certifier (full)
  44. -d|--depth DEPTH trust depth for certifier (1)
  45. remove-id-certifier (c-) KEYID remove a certification key
  46. list-id-certifiers (c) list certification keys
  47. gpg-authentication-cmd CMD gnupg-authentication command
  48. -h|--help|help (h,?) this help
  49. EOF
  50. }
  51. su_monkeysphere_user() {
  52. su --preserve-environment "$MONKEYSPHERE_USER" -- -c "$@"
  53. }
  54. # function to interact with the host gnupg keyring
  55. gpg_host() {
  56. local returnCode
  57. GNUPGHOME="$GNUPGHOME_HOST"
  58. export GNUPGHOME
  59. # NOTE: we supress this warning because we need the monkeysphere
  60. # user to be able to read the host pubring. we realize this might
  61. # be problematic, but it's the simplest solution, without too much
  62. # loss of security.
  63. gpg --no-permission-warning "$@"
  64. returnCode="$?"
  65. # always reset the permissions on the host pubring so that the
  66. # monkeysphere user can read the trust signatures
  67. chgrp "$MONKEYSPHERE_USER" "${GNUPGHOME_HOST}/pubring.gpg"
  68. chmod g+r "${GNUPGHOME_HOST}/pubring.gpg"
  69. return "$returnCode"
  70. }
  71. # function to interact with the authentication gnupg keyring
  72. # FIXME: this function requires basically accepts only a single
  73. # argument because of problems with quote expansion. this needs to be
  74. # fixed/improved.
  75. gpg_authentication() {
  76. GNUPGHOME="$GNUPGHOME_AUTHENTICATION"
  77. export GNUPGHOME
  78. su_monkeysphere_user "gpg $@"
  79. }
  80. # output just key fingerprint
  81. fingerprint_server_key() {
  82. gpg_host --list-secret-keys --fingerprint --with-colons --fixed-list-mode | \
  83. grep '^fpr:' | head -1 | cut -d: -f10
  84. }
  85. # output key information
  86. show_server_key() {
  87. local fingerprint
  88. fingerprint=$(fingerprint_server_key)
  89. gpg_host --fingerprint --list-secret-key "$fingerprint"
  90. }
  91. # update authorized_keys for users
  92. update_users() {
  93. if [ "$1" ] ; then
  94. # get users from command line
  95. unames="$@"
  96. else
  97. # or just look at all users if none specified
  98. unames=$(getent passwd | cut -d: -f1)
  99. fi
  100. # set mode
  101. MODE="authorized_keys"
  102. # set gnupg home
  103. GNUPGHOME="$GNUPGHOME_AUTHENTICATION"
  104. # check to see if the gpg trust database has been initialized
  105. if [ ! -s "${GNUPGHOME}/trustdb.gpg" ] ; then
  106. failure "GNUPG trust database uninitialized. Please see MONKEYSPHERE-SERVER(8)."
  107. fi
  108. # make sure the authorized_keys directory exists
  109. mkdir -p "${VARLIB}/authorized_keys"
  110. # loop over users
  111. for uname in $unames ; do
  112. # check all specified users exist
  113. if ! getent passwd "$uname" >/dev/null ; then
  114. log "----- unknown user '$uname' -----"
  115. continue
  116. fi
  117. # set authorized_user_ids and raw authorized_keys variables,
  118. # translating ssh-style path variables
  119. authorizedUserIDs=$(translate_ssh_variables "$uname" "$AUTHORIZED_USER_IDS")
  120. rawAuthorizedKeys=$(translate_ssh_variables "$uname" "$RAW_AUTHORIZED_KEYS")
  121. # if neither is found, skip user
  122. if [ ! -s "$authorizedUserIDs" ] ; then
  123. if [ "$rawAuthorizedKeys" = '-' -o ! -s "$rawAuthorizedKeys" ] ; then
  124. continue
  125. fi
  126. fi
  127. log "----- user: $uname -----"
  128. # exit if the authorized_user_ids file is empty
  129. if ! check_key_file_permissions "$uname" "$AUTHORIZED_USER_IDS" ; then
  130. log "Improper permissions on authorized_user_ids file path."
  131. continue
  132. fi
  133. # check permissions on the authorized_keys file path
  134. if ! check_key_file_permissions "$uname" "$RAW_AUTHORIZED_KEYS" ; then
  135. log "Improper permissions on authorized_keys file path path."
  136. continue
  137. fi
  138. # make temporary directory
  139. TMPDIR=$(mktemp -d)
  140. # trap to delete temporary directory on exit
  141. trap "rm -rf $TMPDIR" EXIT
  142. # create temporary authorized_user_ids file
  143. TMP_AUTHORIZED_USER_IDS="${TMPDIR}/authorized_user_ids"
  144. touch "$TMP_AUTHORIZED_USER_IDS"
  145. # create temporary authorized_keys file
  146. AUTHORIZED_KEYS="${TMPDIR}/authorized_keys"
  147. touch "$AUTHORIZED_KEYS"
  148. # set restrictive permissions on the temporary files
  149. # FIXME: is there a better way to do this?
  150. chmod 0700 "$TMPDIR"
  151. chmod 0600 "$AUTHORIZED_KEYS"
  152. chmod 0600 "$TMP_AUTHORIZED_USER_IDS"
  153. chown -R "$MONKEYSPHERE_USER" "$TMPDIR"
  154. # if the authorized_user_ids file exists...
  155. if [ -s "$authorizedUserIDs" ] ; then
  156. # copy user authorized_user_ids file to temporary
  157. # location
  158. cat "$authorizedUserIDs" > "$TMP_AUTHORIZED_USER_IDS"
  159. # export needed variables
  160. export AUTHORIZED_KEYS
  161. export TMP_AUTHORIZED_USER_IDS
  162. # process authorized_user_ids file, as monkeysphere
  163. # user
  164. su_monkeysphere_user \
  165. ". ${SHARE}/common; process_authorized_user_ids $TMP_AUTHORIZED_USER_IDS"
  166. RETURN="$?"
  167. fi
  168. # add user-controlled authorized_keys file path if specified
  169. if [ "$rawAuthorizedKeys" != '-' -a -s "$rawAuthorizedKeys" ] ; then
  170. log -n "adding raw authorized_keys file... "
  171. cat "$rawAuthorizedKeys" >> "$AUTHORIZED_KEYS"
  172. loge "done."
  173. fi
  174. # openssh appears to check the contents of the
  175. # authorized_keys file as the user in question, so the
  176. # file must be readable by that user at least.
  177. # FIXME: is there a better way to do this?
  178. chown root "$AUTHORIZED_KEYS"
  179. chgrp $(getent passwd "$uname" | cut -f4 -d:) "$AUTHORIZED_KEYS"
  180. chmod g+r "$AUTHORIZED_KEYS"
  181. # move the resulting authorized_keys file into place
  182. mv -f "$AUTHORIZED_KEYS" "${VARLIB}/authorized_keys/${uname}"
  183. # destroy temporary directory
  184. rm -rf "$TMPDIR"
  185. done
  186. }
  187. # generate server gpg key
  188. gen_key() {
  189. local keyType
  190. local keyLength
  191. local keyUsage
  192. local keyExpire
  193. local revoker
  194. local hostName
  195. local userID
  196. local keyParameters
  197. local fingerprint
  198. # set default key parameter values
  199. keyType="RSA"
  200. keyLength="2048"
  201. keyUsage="auth"
  202. keyExpire=
  203. revoker=
  204. # get options
  205. TEMP=$(getopt -o e:l:r -l expire:,length:,revoker: -n "$PGRM" -- "$@")
  206. if [ $? != 0 ] ; then
  207. exit 1
  208. fi
  209. # Note the quotes around `$TEMP': they are essential!
  210. eval set -- "$TEMP"
  211. while true ; do
  212. case "$1" in
  213. -l|--length)
  214. keyLength="$2"
  215. shift 2
  216. ;;
  217. -e|--expire)
  218. keyExpire="$2"
  219. shift 2
  220. ;;
  221. -r|--revoker)
  222. revoker="$2"
  223. shift 2
  224. ;;
  225. --)
  226. shift
  227. ;;
  228. *)
  229. break
  230. ;;
  231. esac
  232. done
  233. hostName=${1:-$(hostname --fqdn)}
  234. userID="ssh://${hostName}"
  235. # check for presense of key with user ID
  236. if gpg_host --list-key ="$userID" > /dev/null 2>&1 ; then
  237. failure "Key for '$userID' already exists"
  238. fi
  239. # prompt about key expiration if not specified
  240. if [ -z "$keyExpire" ] ; then
  241. cat <<EOF
  242. Please specify how long the key should be valid.
  243. 0 = key does not expire
  244. <n> = key expires in n days
  245. <n>w = key expires in n weeks
  246. <n>m = key expires in n months
  247. <n>y = key expires in n years
  248. EOF
  249. while [ -z "$keyExpire" ] ; do
  250. read -p "Key is valid for? (0) " keyExpire
  251. if ! test_gpg_expire ${keyExpire:=0} ; then
  252. echo "invalid value"
  253. unset keyExpire
  254. fi
  255. done
  256. elif ! test_gpg_expire "$keyExpire" ; then
  257. failure "invalid key expiration value '$keyExpire'."
  258. fi
  259. # set key parameters
  260. keyParameters=$(cat <<EOF
  261. Key-Type: $keyType
  262. Key-Length: $keyLength
  263. Key-Usage: $keyUsage
  264. Name-Real: $userID
  265. Expire-Date: $keyExpire
  266. EOF
  267. )
  268. # add the revoker field if specified
  269. # FIXME: the "1:" below assumes that $REVOKER's key is an RSA key.
  270. # FIXME: key is marked "sensitive"? is this appropriate?
  271. if [ "$revoker" ] ; then
  272. keyParameters="${keyParameters}"$(cat <<EOF
  273. Revoker: 1:$revoker sensitive
  274. EOF
  275. )
  276. fi
  277. echo "The following key parameters will be used for the host private key:"
  278. echo "$keyParameters"
  279. read -p "Generate key? (Y/n) " OK; OK=${OK:=Y}
  280. if [ ${OK/y/Y} != 'Y' ] ; then
  281. failure "aborting."
  282. fi
  283. # add commit command
  284. keyParameters="${keyParameters}"$(cat <<EOF
  285. %commit
  286. %echo done
  287. EOF
  288. )
  289. log "generating server key..."
  290. echo "$keyParameters" | gpg_host --batch --gen-key
  291. # output the server fingerprint
  292. fingerprint_server_key "=${userID}"
  293. # find the key fingerprint of the newly generated key
  294. fingerprint=$(fingerprint_server_key)
  295. # export host ownertrust to authentication keyring
  296. log "setting ultimate owner trust for server key..."
  297. echo "${fingerprint}:6:" | gpg_authentication "--import-ownertrust"
  298. # translate the private key to ssh format, and export to a file
  299. # for sshs usage.
  300. # NOTE: assumes that the primary key is the proper key to use
  301. (umask 077 && \
  302. gpg_host --export-secret-key "$fingerprint" | \
  303. openpgp2ssh "$fingerprint" > "${VARLIB}/ssh_host_rsa_key")
  304. log "Private SSH host key output to file: ${VARLIB}/ssh_host_rsa_key"
  305. }
  306. # add hostname user ID to server key
  307. add_hostname() {
  308. local userID
  309. local fingerprint
  310. local tmpuidMatch
  311. local line
  312. local adduidCommand
  313. if [ -z "$1" ] ; then
  314. failure "You must specify a hostname to add."
  315. fi
  316. userID="ssh://${1}"
  317. fingerprint=$(fingerprint_server_key)
  318. # match to only ultimately trusted user IDs
  319. tmpuidMatch="u:$(echo $userID | gpg_escape)"
  320. # find the index of the requsted user ID
  321. # NOTE: this is based on circumstantial evidence that the order of
  322. # this output is the appropriate index
  323. if line=$(gpg_host --list-keys --with-colons --fixed-list-mode "0x${fingerprint}"\! \
  324. | egrep '^(uid|uat):' | cut -f2,10 -d: | grep -n -x -F "$tmpuidMatch") ; then
  325. failure "Host userID '$userID' already exists."
  326. fi
  327. echo "The following user ID will be added to the host key:"
  328. echo " $userID"
  329. read -p "Are you sure you would like to add this user ID? (y/N) " OK; OK=${OK:=N}
  330. if [ ${OK/y/Y} != 'Y' ] ; then
  331. failure "user ID not added."
  332. fi
  333. # edit-key script command to add user ID
  334. adduidCommand=$(cat <<EOF
  335. adduid
  336. $userID
  337. save
  338. EOF
  339. )
  340. # execute edit-key script
  341. if echo "$adduidCommand" | gpg_host --quiet --command-fd 0 --edit-key "0x${fingerprint}"\! ; then
  342. # update trust db
  343. gpg_host --check-trustdb
  344. show_server_key
  345. echo "NOTE: User ID added but key not published."
  346. echo "Run '$PGRM publish-key' to publish the key"
  347. else
  348. failure "Problem adding user ID."
  349. fi
  350. }
  351. # revoke hostname user ID to server key
  352. revoke_hostname() {
  353. local userID
  354. local fingerprint
  355. local tmpuidMatch
  356. local line
  357. local uidIndex
  358. local message
  359. local revuidCommand
  360. if [ -z "$1" ] ; then
  361. failure "You must specify a hostname to revoke."
  362. fi
  363. userID="ssh://${1}"
  364. fingerprint=$(fingerprint_server_key)
  365. # match to only ultimately trusted user IDs
  366. tmpuidMatch="u:$(echo $userID | gpg_escape)"
  367. # find the index of the requsted user ID
  368. # NOTE: this is based on circumstantial evidence that the order of
  369. # this output is the appropriate index
  370. if line=$(gpg_host --list-keys --with-colons --fixed-list-mode "0x${fingerprint}"\! \
  371. | egrep '^(uid|uat):' | cut -f2,10 -d: | grep -n -x -F "$tmpuidMatch") ; then
  372. uidIndex=${line%%:*}
  373. else
  374. failure "No non-revoked user ID '$userID' is found."
  375. fi
  376. echo "The following user ID will be revoked from the host key:"
  377. echo " $userID"
  378. read -p "Are you sure you would like to revoke this user ID? (y/N) " OK; OK=${OK:=N}
  379. if [ ${OK/y/Y} != 'Y' ] ; then
  380. failure "user ID not revoked."
  381. fi
  382. message="Hostname removed by monkeysphere-server $DATE"
  383. # edit-key script command to revoke user ID
  384. revuidCommand=$(cat <<EOF
  385. $uidIndex
  386. revuid
  387. y
  388. 4
  389. $message
  390. y
  391. save
  392. EOF
  393. )
  394. # execute edit-key script
  395. if echo "$revuidCommand" | gpg_host --quiet --command-fd 0 --edit-key "0x${fingerprint}"\! ; then
  396. # update trust db
  397. gpg_host --check-trustdb
  398. show_server_key
  399. echo "NOTE: User ID revoked but key not published."
  400. echo "Run '$PGRM publish-key' to publish the key"
  401. else
  402. failure "Problem revoking user ID."
  403. fi
  404. }
  405. # publish server key to keyserver
  406. publish_server_key() {
  407. read -p "Really publish host key to $KEYSERVER? (y/N) " OK; OK=${OK:=N}
  408. if [ ${OK/y/Y} != 'Y' ] ; then
  409. failure "key not published."
  410. fi
  411. # find the key fingerprint
  412. fingerprint=$(fingerprint_server_key)
  413. # publish host key
  414. gpg_authentication "--keyserver $KEYSERVER --send-keys $fingerprint"
  415. }
  416. diagnostics() {
  417. # * check on the status and validity of the key and public certificates
  418. local seckey
  419. local keysfound
  420. local curdate
  421. local warnwindow
  422. local warndate
  423. local create
  424. local expire
  425. local uid
  426. local fingerprint
  427. local badhostkeys
  428. local sshd_config
  429. # FIXME: what's the correct, cross-platform answer?
  430. sshd_config=/etc/ssh/sshd_config
  431. seckey=$(fingerprint_server_key)
  432. keysfound=$(echo "$seckey" | grep -c ^sec:)
  433. curdate=$(date +%s)
  434. # warn when anything is 2 months away from expiration
  435. warnwindow='2 months'
  436. warndate=$(date +%s -d "$warnwindow")
  437. echo "Checking host GPG key..."
  438. if (( "$keysfound" < 1 )); then
  439. echo "! No host key found."
  440. echo " - Recommendation: run 'monkeysphere-server gen-key'"
  441. elif (( "$keysfound" > 1 )); then
  442. echo "! More than one host key found?"
  443. # FIXME: recommend a way to resolve this
  444. else
  445. create=$(echo "$seckey" | grep ^sec: | cut -f6 -d:)
  446. expire=$(echo "$seckey" | grep ^sec: | cut -f7 -d:)
  447. fingerprint=$(echo "$seckey" | grep ^fpr: | head -n1 | cut -f10 -d:)
  448. # check for key expiration:
  449. if [ "$expire" ]; then
  450. if (( "$expire" < "$curdate" )); then
  451. echo "! Host key is expired."
  452. # FIXME: recommend a way to resolve this other than re-keying?
  453. elif (( "$expire" < "$warndate" )); then
  454. echo "! Host key expires in less than $warnwindow:" $(date -d "$(( $expire - $curdate )) seconds" +%F)
  455. # FIXME: recommend a way to resolve this?
  456. fi
  457. fi
  458. # and weirdnesses:
  459. if [ "$create" ] && (( "$create" > "$curdate" )); then
  460. echo "! Host key was created in the future(?!). Is your clock correct?"
  461. echo " - Recommendation: Check clock ($(date +%F_%T)); use NTP?"
  462. fi
  463. # check for UserID expiration:
  464. echo "$seckey" | grep ^uid: | cut -d: -f6,7,10 | \
  465. while IFS=: read create expire uid ; do
  466. # FIXME: should we be doing any checking on the form
  467. # of the User ID? Should we be unmangling it somehow?
  468. if [ "$create" ] && (( "$create" > "$curdate" )); then
  469. echo "! User ID '$uid' was created in the future(?!). Is your clock correct?"
  470. echo " - Recommendation: Check clock ($(date +%F_%T)); use NTP?"
  471. fi
  472. if [ "$expire" ] ; then
  473. if (( "$expire" < "$curdate" )); then
  474. echo "! User ID '$uid' is expired."
  475. # FIXME: recommend a way to resolve this
  476. elif (( "$expire" < "$warndate" )); then
  477. echo "! User ID '$uid' expires in less than $warnwindow:" $(date -d "$(( $expire - $curdate )) seconds" +%F)
  478. # FIXME: recommend a way to resolve this
  479. fi
  480. fi
  481. done
  482. # FIXME: verify that the host key is properly published to the
  483. # keyservers (do this with the non-privileged user)
  484. # FIXME: check that there are valid, non-expired certifying signatures
  485. # attached to the host key after fetching from the public keyserver
  486. # (do this with the non-privileged user as well)
  487. # FIXME: propose adding a revoker to the host key if none exist (do we
  488. # have a way to do that after key generation?)
  489. # Ensure that the ssh_host_rsa_key file is present and non-empty:
  490. echo "Checking host SSH key..."
  491. if [ ! -s "${VARLIB}/ssh_host_rsa_key" ] ; then
  492. echo "! The host key as prepared for SSH (${VARLIB}/ssh_host_rsa_key) is missing or empty."
  493. else
  494. if [ $(stat -c '%a' "${VARLIB}/ssh_host_rsa_key") != 600 ] ; then
  495. echo "! Permissions seem wrong for ${VARLIB}/ssh_host_rsa_key -- should be 0600."
  496. fi
  497. # propose changes needed for sshd_config (if any)
  498. if ! grep -q "^HostKey[[:space:]]\+${VARLIB}/ssh_host_rsa_key$" "$sshd_config"; then
  499. echo "! $sshd_config does not point to the monkeysphere host key (${VARLIB}/ssh_host_rsa_key)."
  500. echo " - Recommendation: add a line to $sshd_config: 'HostKey ${VARLIB}/ssh_host_rsa_key'"
  501. fi
  502. if badhostkeys=$(grep -i '^HostKey' "$sshd_config" | grep -q -v "^HostKey[[:space:]]\+${VARLIB}/ssh_host_rsa_key$") ; then
  503. echo "! /etc/sshd_config refers to some non-monkeysphere host keys:"
  504. echo "$badhostkeys"
  505. echo " - Recommendation: remove the above HostKey lines from $sshd_config"
  506. fi
  507. fi
  508. fi
  509. # FIXME: look at the ownership/privileges of the various keyrings,
  510. # directories housing them, etc (what should those values be? can
  511. # we make them as minimal as possible?)
  512. # FIXME: look to see that the ownertrust rules are set properly on the
  513. # authentication keyring
  514. # FIXME: make sure that at least one identity certifier exists
  515. echo "Checking for MonkeySphere-enabled public-key authentication for users ..."
  516. # Ensure that User ID authentication is enabled:
  517. if ! grep -q "^AuthorizedKeysFile[[:space:]]\+${VARLIB}/authorized_keys/%u$" "$sshd_config"; then
  518. echo "! $sshd_config does not point to monkeysphere authorized keys."
  519. echo " - Recommendation: add a line to $sshd_config: 'AuthorizedKeysFile ${VARLIB}/authorized_keys/%u'"
  520. fi
  521. if badauthorizedkeys=$(grep -i '^AuthorizedKeysFile' "$sshd_config" | grep -q -v "^AuthorizedKeysFile[[:space:]]\+${VARLIB}/authorized_keys/%u$") ; then
  522. echo "! /etc/sshd_config refers to non-monkeysphere authorized_keys files:"
  523. echo "$badauthorizedkeys"
  524. echo " - Recommendation: remove the above AuthorizedKeysFile lines from $sshd_config"
  525. fi
  526. }
  527. # retrieve key from web of trust, import it into the host keyring, and
  528. # ltsign the key in the host keyring so that it may certify other keys
  529. add_certifier() {
  530. local domain
  531. local trust
  532. local depth
  533. local keyID
  534. local fingerprint
  535. local ltsignCommand
  536. local trustval
  537. # set default values for trust depth and domain
  538. domain=
  539. trust=full
  540. depth=1
  541. # get options
  542. TEMP=$(getopt -o n:t:d: -l domain:,trust:,depth: -n "$PGRM" -- "$@")
  543. if [ $? != 0 ] ; then
  544. exit 1
  545. fi
  546. # Note the quotes around `$TEMP': they are essential!
  547. eval set -- "$TEMP"
  548. while true ; do
  549. case "$1" in
  550. -n|--domain)
  551. domain="$2"
  552. shift 2
  553. ;;
  554. -t|--trust)
  555. trust="$2"
  556. shift 2
  557. ;;
  558. -d|--depth)
  559. depth="$2"
  560. shift 2
  561. ;;
  562. --)
  563. shift
  564. ;;
  565. *)
  566. break
  567. ;;
  568. esac
  569. done
  570. keyID="$1"
  571. if [ -z "$keyID" ] ; then
  572. failure "You must specify the key ID of a key to add."
  573. fi
  574. export keyID
  575. # get the key from the key server
  576. gpg_authentication "--keyserver $KEYSERVER --recv-key '$keyID'"
  577. # get the full fingerprint of a key ID
  578. fingerprint=$(gpg_authentication "--list-key --with-colons --with-fingerprint $keyID" | \
  579. grep '^fpr:' | grep "$keyID" | cut -d: -f10)
  580. echo "key found:"
  581. gpg_authentication "--fingerprint $fingerprint"
  582. echo "Are you sure you want to add this key as a certifier of"
  583. read -p "users on this system? (y/N) " OK; OK=${OK:-N}
  584. if [ "${OK/y/Y}" != 'Y' ] ; then
  585. failure "aborting."
  586. fi
  587. # export the key to the host keyring
  588. gpg_authentication "--export $keyID" | gpg_host --import
  589. if [ "$trust" == marginal ]; then
  590. trustval=1
  591. elif [ "$trust" == full ]; then
  592. trustval=2
  593. else
  594. failure "trust value requested ('$trust') was unclear (only 'marginal' or 'full' are supported)"
  595. fi
  596. # ltsign command
  597. # NOTE: *all* user IDs will be ltsigned
  598. ltsignCommand=$(cat <<EOF
  599. ltsign
  600. y
  601. $trustval
  602. $depth
  603. $domain
  604. y
  605. save
  606. EOF
  607. )
  608. # ltsign the key
  609. echo "$ltsignCommand" | gpg_host --quiet --command-fd 0 --edit-key "0x${fingerprint}"\!
  610. # update the trustdb for the authentication keyring
  611. gpg_authentication "--check-trustdb"
  612. }
  613. # delete a certifiers key from the host keyring
  614. remove_certifier() {
  615. local keyID
  616. local fingerprint
  617. keyID="$1"
  618. if [ -z "$keyID" ] ; then
  619. failure "You must specify the key ID of a key to remove."
  620. fi
  621. # delete the requested key (with prompting)
  622. gpg_host --delete-key "$keyID"
  623. # update the trustdb for the authentication keyring
  624. gpg_authentication "--check-trustdb"
  625. }
  626. # list the host certifiers
  627. list_certifiers() {
  628. gpg_host --list-keys
  629. }
  630. # issue command to gpg-authentication keyring
  631. gpg_authentication_cmd() {
  632. gpg_authentication "$@"
  633. }
  634. ########################################################################
  635. # MAIN
  636. ########################################################################
  637. # unset variables that should be defined only in config file
  638. unset KEYSERVER
  639. unset AUTHORIZED_USER_IDS
  640. unset RAW_AUTHORIZED_KEYS
  641. unset MONKEYSPHERE_USER
  642. # load configuration file
  643. [ -e ${MONKEYSPHERE_SERVER_CONFIG:="${ETC}/monkeysphere-server.conf"} ] && . "$MONKEYSPHERE_SERVER_CONFIG"
  644. # set empty config variable with ones from the environment, or with
  645. # defaults
  646. KEYSERVER=${MONKEYSPHERE_KEYSERVER:=${KEYSERVER:="subkeys.pgp.net"}}
  647. AUTHORIZED_USER_IDS=${MONKEYSPHERE_AUTHORIZED_USER_IDS:=${AUTHORIZED_USER_IDS:="%h/.config/monkeysphere/authorized_user_ids"}}
  648. RAW_AUTHORIZED_KEYS=${MONKEYSPHERE_RAW_AUTHORIZED_KEYS:=${RAW_AUTHORIZED_KEYS:="%h/.ssh/authorized_keys"}}
  649. MONKEYSPHERE_USER=${MONKEYSPHERE_MONKEYSPHERE_USER:=${MONKEYSPHERE_USER:="monkeysphere"}}
  650. # other variables
  651. CHECK_KEYSERVER=${MONKEYSPHERE_CHECK_KEYSERVER:="true"}
  652. REQUIRED_USER_KEY_CAPABILITY=${MONKEYSPHERE_REQUIRED_USER_KEY_CAPABILITY:="a"}
  653. GNUPGHOME_HOST=${MONKEYSPHERE_GNUPGHOME_HOST:="${VARLIB}/gnupg-host"}
  654. GNUPGHOME_AUTHENTICATION=${MONKEYSPHERE_GNUPGHOME_AUTHENTICATION:="${VARLIB}/gnupg-authentication"}
  655. # export variables needed in su invocation
  656. export DATE
  657. export MODE
  658. export MONKEYSPHERE_USER
  659. export KEYSERVER
  660. export CHECK_KEYSERVER
  661. export REQUIRED_USER_KEY_CAPABILITY
  662. export GNUPGHOME_HOST
  663. export GNUPGHOME_AUTHENTICATION
  664. export GNUPGHOME
  665. # get subcommand
  666. COMMAND="$1"
  667. [ "$COMMAND" ] || failure "Type '$PGRM help' for usage."
  668. shift
  669. case $COMMAND in
  670. 'update-users'|'update-user'|'u')
  671. update_users "$@"
  672. ;;
  673. 'gen-key'|'g')
  674. gen_key "$@"
  675. ;;
  676. 'add-hostname'|'add-name'|'n+')
  677. add_hostname "$@"
  678. ;;
  679. 'revoke-hostname'|'revoke-name'|'n-')
  680. revoke_hostname "$@"
  681. ;;
  682. 'show-key'|'show'|'s')
  683. show_server_key
  684. ;;
  685. 'show-fingerprint'|'fingerprint'|'f')
  686. fingerprint_server_key
  687. ;;
  688. 'publish-key'|'publish'|'p')
  689. publish_server_key
  690. ;;
  691. 'diagnostics'|'d')
  692. diagnostics
  693. ;;
  694. 'add-identity-certifier'|'add-id-certifier'|'add-certifier'|'c+')
  695. add_certifier "$@"
  696. ;;
  697. 'remove-identity-certifier'|'remove-id-certifier'|'remove-certifier'|'c-')
  698. remove_certifier "$@"
  699. ;;
  700. 'list-identity-certifiers'|'list-id-certifiers'|'list-certifiers'|'list-certifier'|'c')
  701. list_certifiers "$@"
  702. ;;
  703. 'gpg-authentication-cmd')
  704. gpg_authentication_cmd "$@"
  705. ;;
  706. '--help'|'help'|'-h'|'h'|'?')
  707. usage
  708. ;;
  709. *)
  710. failure "Unknown command: '$COMMAND'
  711. Type '$PGRM help' for usage."
  712. ;;
  713. esac
  714. exit "$RETURN"