Useful CLI tools (bash) for Arch Linux administration
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

217 lines
7.6 KiB

6 years ago
  1. #!/bin/bash
  2. # archrisks - Security information tool for Arch Linux
  3. # Copyright (C) 2018 Pekka Helenius
  4. #
  5. # This program is free software: you can redistribute it and/or modify
  6. # it under the terms of the GNU General Public License as published by
  7. # the Free Software Foundation, either version 3 of the License, or
  8. # (at your option) any later version.
  9. #
  10. # This program is distributed in the hope that it will be useful,
  11. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. # GNU General Public License for more details.
  14. #
  15. # You should have received a copy of the GNU General Public License
  16. # along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. ######################################################################################################################
  18. if [[ ! $(id -u) -eq 0 ]]; then
  19. echo -e "\nThis command requires root privileges.\n"
  20. exit
  21. fi
  22. echo "Security report date: $(date '+%d-%m-%Y, %X') (TZ: $(timedatectl status | grep "Time zone:" | awk '{print $3}'))"
  23. red=$'\33[91m'
  24. orange=$'\033[38;5;208m'
  25. yellow=$'\033[93m'
  26. green=$'\033[92m'
  27. reset=$'\033[0m'
  28. PROVIDER="security.archlinux.org"
  29. # pacman, pacaur or yaourt. Please make sure all parameters used in this script are accepted by PKGMGR
  30. PKGMGR="pacman"
  31. INTERNET_TEST=$(ping -c 1 $PROVIDER 2>&1 | grep -c "Name or service not known")
  32. if [[ ! $INTERNET_TEST -eq 0 ]]; then
  33. echo -e "\nCan't connect to $PROVIDER. Please check your internet connection and try again.\n"
  34. else
  35. echo -e "\nSynchronizing package databases with $PKGMGR\n"
  36. $PKGMGR -Syy || return
  37. if [[ ! $(which arch-audit | wc -l) -eq 1 ]]; then
  38. echo -e "\nCouldn't find Arch Linux security utility (arch-audit). Please make sure it's installed.\n"
  39. else
  40. CNT=0
  41. PRSCNT=0
  42. # Internal Field Separator. This variable determines how Bash recognizes fields, or word boundaries, when it interprets character strings.
  43. IFS=$'\n'
  44. for i in $(arch-audit); do
  45. PACKAGENAME=$(echo "$i" | awk -F ' ' '{print $2}')
  46. RISKLEVEL=$(echo "$i" | grep -oE "Low|Medium|High|Critical")
  47. RISKSCOUNT=$(echo "$i" | awk -F 'CVE' '{print NF-1}')
  48. RISKS[$CNT]="$PACKAGENAME $RISKLEVEL $RISKSCOUNT"
  49. let CNT++
  50. done
  51. echo -e "\e[1m"
  52. printf "%-25s%-20s%-15s%-25s%s\n" "Package" "Security issues" "Risk level" "Version status" "Description"
  53. echo -e "\e[0m"
  54. for RISK_PARSED in $(echo "${RISKS[*]}"); do
  55. # Package in question
  56. col1=$(echo "$RISK_PARSED" | awk -F ' ' '{print $1}')
  57. # Security issues detected
  58. col2=$(echo "$RISK_PARSED" | awk -F ' ' '{print $3}')
  59. #Critical, High, Medium or Low risk
  60. col3=$(echo "$RISK_PARSED" | awk -F ' ' '{print $2}' | sed 's/Critical/0/g; s/High/1/g; s/Medium/2/g; s/Low/3/g')
  61. col5=$($PKGMGR -Qi $col1 |grep -i description | awk -F ": " '{print $2}')
  62. maxchars=35
  63. if [[ $(echo $col5 | wc -m) -gt $maxchars ]]; then
  64. col5=$(echo "$(echo $col5 | cut -c 1-$maxchars)...")
  65. fi
  66. #pkgurl=$(pacaur -Qi $col1 |grep URL | awk -F ": " '{print $2}')
  67. versioncheck() {
  68. parsedver() {
  69. TRIMMED=$(echo $1 | sed 's/[:.-]/./g')
  70. if [[ $TRIMMED =~ [A-Za-z] ]]; then
  71. PKGVERCHARS=$(echo $TRIMMED | sed 's/[^a-zA-Z]//g')
  72. CHARNUM=0
  73. for char in $PKGVERCHARS; do
  74. charnum=$(echo {a..z} | sed 's/ //g' | grep -b -o $char | awk 'BEGIN {FS=":"}{print $1}')
  75. REP[$CHARNUM]="s/$char/$charnum/g;"
  76. let CHARNUM++
  77. done
  78. for seds in "${REP[*]}"; do
  79. SEDSTR=$seds
  80. done
  81. echo $TRIMMED | sed "$SEDSTR"
  82. else
  83. echo $TRIMMED
  84. fi
  85. }
  86. SYSVER=$($PKGMGR -Q $1 | awk -F ' ' '{print $2}')
  87. REPOVER=$($PKGMGR -Si $1 | grep "Version.*:" | awk -F ' ' '{print $3}')
  88. VERARRAY1=$(parsedver $SYSVER)
  89. VERARRAY2=$(parsedver $REPOVER)
  90. #Count of version elements (0 18 2 1 contains 4 numbers, for example)
  91. firstvernums=$(echo $VERARRAY1 | awk -F '.' '{print split($0, a)}')
  92. lastvernums=$(echo $VERARRAY2 | awk -F '.' '{print split($0, a)}')
  93. # Count of comparable version elements (maximum)
  94. # We compare this much of elements, not more
  95. if [[ $lastvernums -lt $firstvernums ]]; then
  96. comparables=$lastvernums
  97. else
  98. comparables=$firstvernums
  99. fi
  100. # If all numbers are same, we don't analyze them more deeply.
  101. if [[ $VERARRAY1 == $VERARRAY2 ]]; then
  102. col4="${green}Package is updated"
  103. else
  104. s=1
  105. while [ $s -le $comparables ]; do
  106. check1=$(echo -e $VERARRAY1 | awk -v var=$s -F '.' '{print $var}')
  107. check2=$(echo -e $VERARRAY2 | awk -v var=$s -F '.' '{print $var}')
  108. if [[ $check2 -gt $check1 ]]; then
  109. # Repo number is greater
  110. col4="${yellow}Update available"
  111. break
  112. elif [[ $check2 -lt $check1 ]]; then
  113. # System number is greater
  114. col4="${reset}Newer package installed"
  115. break
  116. fi
  117. let s++
  118. done
  119. fi
  120. }
  121. versioncheck $col1
  122. RISKENTRIES[$PRSCNT]=$(printf "%s|%s|%s|%s|%s\n" "$col1" "$col2" "$col3" "$col4" "$col5")
  123. let PRSCNT++
  124. done
  125. i=0
  126. for line in $(echo "${RISKENTRIES[*]}" | sort -t'|' -k3); do
  127. if [[ $(echo "$line" | awk -F '|' '{print $3}') -eq 0 ]]; then
  128. alertclr="${red}"
  129. IMPT="Critical"
  130. elif [[ $(echo "$line" | awk -F '|' '{print $3}') -eq 1 ]]; then
  131. alertclr="${orange}"
  132. IMPT="High"
  133. elif [[ $(echo "$line" | awk -F '|' '{print $3}') -eq 2 ]]; then
  134. alertclr="${yellow}"
  135. IMPT="Medium"
  136. elif [[ $(echo "$line" | awk -F '|' '{print $3}') -eq 3 ]]; then
  137. alertclr="${green}"
  138. IMPT="Low"
  139. fi
  140. SECCOUNT=$(echo "$line" | awk -F '|' '{print $2}')
  141. if [[ $SECCOUNT -lt 5 ]]; then
  142. secclr="${green}"
  143. elif [[ $SECCOUNT -ge 5 ]] && [[ $SECCOUNT -lt 10 ]]; then
  144. secclr="${yellow}"
  145. elif [[ $SECCOUNT -ge 10 ]] && [[ $SECCOUNT -lt 20 ]]; then
  146. secclr="${orange}"
  147. elif [[ $SECCOUNT -ge 20 ]]; then
  148. secclr="${red}"
  149. fi
  150. secsum[$i]=$SECCOUNT
  151. echo "$line" | awk -F '|' -v clr1="${alertclr}" -v clr2="${secclr}" -v rs="${reset}" -v var="${IMPT}" '{printf "%-25s%s%-20s%s%-15s%-30s%s%s\n",$1,clr2,$2,clr1,var,$4,rs,$5}'
  152. let i++
  153. done
  154. secsums_total=$(echo $(printf "%d+" ${secsum[@]})0 | bc)
  155. echo -e "\nTotal:"
  156. printf "%-25s%s\n\n" "$CNT" "$secsums_total"
  157. fi
  158. fi