| 1 |
#!/bin/ksh |
| 2 |
# |
| 3 |
# KSH93 only (floating point) |
| 4 |
# |
| 5 |
set -e |
| 6 |
|
| 7 |
debug=0 |
| 8 |
|
| 9 |
[[ -z $1 ]] && echo want \$shot && exit 1 |
| 10 |
shot=$1 |
| 11 |
|
| 12 |
LC_NUMERIC=en_US |
| 13 |
#sep="sed ':a;s/\B[0-9]\{3\}\>/,&/;ta'" |
| 14 |
#| eval $sep |
| 15 |
|
| 16 |
echo -n entering ~/$shot/splitted/ ... |
| 17 |
cd ~/$shot/splitted/ && echo done |
| 18 |
|
| 19 |
#based on exclude.conf |
| 20 |
internet=3970693888 |
| 21 |
|
| 22 |
range=`seq -w 00 89; seq 9000 9447` |
| 23 |
|
| 24 |
(( debug == 1 )) && counting inbound smtp hosts |
| 25 |
#smtp=0 |
| 26 |
#for x in $range; do |
| 27 |
# (( smtp = smtp + `grep -v ^# x$x | wc -l` )) || echo FAIL:x$x |
| 28 |
#done; unset x |
| 29 |
smtp=`grep -v ^# ../massp25.og | wc -l` |
| 30 |
|
| 31 |
(( debug == 1 )) && echo counting hosts which iprev resolve x\*.ptr |
| 32 |
(( iprev = `cat x*.ptr | wc -l` )) |
| 33 |
|
| 34 |
(( debug == 1 )) && echo counting unique iprev hosts |
| 35 |
iprevu=`wc -l < ptr.unique` |
| 36 |
|
| 37 |
(( debug == 1 )) && echo counting those which do not talk SSL x\*.ptr.nossl |
| 38 |
nossl=0 |
| 39 |
for x in $range; do |
| 40 |
(( nossl = nossl + `wc -l < x$x.ptr.nossl` )) || echo FAIL:x$x |
| 41 |
done; unset x |
| 42 |
|
| 43 |
(( debug == 1 )) && echo counting those which have wrong SAN x\*.ptr.wrongcn |
| 44 |
wrongcn=0 |
| 45 |
for x in $range; do |
| 46 |
(( wrongcn = wrongcn + `wc -l < x$x.ptr.wrongcn` )) || echo FAIL:x$x |
| 47 |
done; unset x |
| 48 |
|
| 49 |
(( debug == 1 )) && echo counting those which have valid SAN x\*.ptr.validcn |
| 50 |
validcn=0 |
| 51 |
for x in $range; do |
| 52 |
(( validcn = validcn + `wc -l < x$x.ptr.validcn` )) || echo FAIL:x$x |
| 53 |
done; unset x |
| 54 |
|
| 55 |
(( debug == 1 )) && echo counting those which validate x\*.ptr.validcn.return |
| 56 |
(( validate = `grep 'Verify return code: 0 (ok)' x*.ptr.validcn.return | wc -l` )) || echo FAIL |
| 57 |
|
| 58 |
echo |
| 59 |
printf "internet is\\t\\t%'.f\n" $internet |
| 60 |
printf "inbound smtp hosts are\\t%'.f\n" $smtp |
| 61 |
printf "iprev are\\t\\t%'.f\n" $iprev |
| 62 |
printf "unique iprev are\\t%'.f\n" $iprevu |
| 63 |
printf "no ssl are\\t\\t%'.f\n" $nossl |
| 64 |
printf "wrong CN/SAN are\\t%'.f\n" $wrongcn |
| 65 |
printf "iprev CN/SAN are\\t%'.f\n" $validcn |
| 66 |
printf "valid chains are\\t%'.f\n" $validate |
| 67 |
|
| 68 |
typeset -F2 internet smtp iprev iprevu nossl wrongcn validcn validate |
| 69 |
typeset -F2 ssldiff iprevdiff |
| 70 |
|
| 71 |
(( ssldiff = iprev - nossl )) |
| 72 |
(( iprevdiff = iprev - iprevu )) |
| 73 |
|
| 74 |
typeset -F2 result |
| 75 |
|
| 76 |
echo |
| 77 |
|
| 78 |
(( result = smtp * 100 / internet )) |
| 79 |
echo $result% of the public network listens on port 25/tcp - ${smtp%\.*} out of ${internet%\.*} |
| 80 |
|
| 81 |
(( result = iprev * 100 / smtp )) |
| 82 |
echo $result% of the smtp servers are full-circle reverse DNS - ${iprev%\.*} out of ${smtp%\.*} |
| 83 |
|
| 84 |
(( result = iprevdiff * 100 / iprev )) |
| 85 |
echo $result% of those iprev hosts are multi-homed \(round-robin\) - ${iprevdiff%\.*} out of ${iprev%\.*} |
| 86 |
|
| 87 |
(( result = ssldiff * 100 / iprev )) |
| 88 |
echo $result% of full-circle hosts talk SSL/STARTTLS - ${ssldiff%\.*} out of ${iprev%\.*} |
| 89 |
|
| 90 |
#echo $(( validcn * 100 / iprev ))% of full-circle hosts advertise a valid subject alternative - ${validcn%\.*} out of ${iprev%\.*} |
| 91 |
|
| 92 |
(( result = validcn * 100 / ssldiff )) |
| 93 |
echo $result% of SSL-enabled hosts advertise an iprev subject alternative name - ${validcn%\.*} out of ${ssldiff%\.*} |
| 94 |
|
| 95 |
(( result = validate * 100 / validcn )) |
| 96 |
echo $result% of SAN hosts have a valid certificate chain - ${validate%\.*} out of ${validcn%\.*} |
| 97 |
|
| 98 |
echo |
| 99 |
|
| 100 |
# |
| 101 |
# here comes stats based on MX records |
| 102 |
# |
| 103 |
|
| 104 |
ptrs=`wc -l < ptr.unique` |
| 105 |
|
| 106 |
cd domains/ |
| 107 |
|
| 108 |
domains=`wc -l < domains.unique` |
| 109 |
|
| 110 |
cd mx/ |
| 111 |
|
| 112 |
mx=`wc -l < mx.unique` |
| 113 |
|
| 114 |
cd dane/ |
| 115 |
|
| 116 |
(( debug == 1 )) && echo counting trueok |
| 117 |
trueok=`grep '0 (ok)$' *.ssl | grep -v 'New, (NONE), Cipher is (NONE)' | wc -l` |
| 118 |
|
| 119 |
(( debug == 1 )) && echo counting fakeok |
| 120 |
fakeok=`grep '0 (ok)$' *.ssl | grep 'New, (NONE), Cipher is (NONE)' | wc -l` |
| 121 |
|
| 122 |
#grep 'Verify return code: ' mx.unique37.ssl | cut -f2 -d: | sort -u |
| 123 |
(( debug == 1 )) && echo counting notyet |
| 124 |
notyet=`grep '9 (certificate is not yet valid)$' *.ssl | wc -l` |
| 125 |
|
| 126 |
(( debug == 1 )) && echo counting expired |
| 127 |
expired=`grep '10 (certificate has expired)$' *.ssl | wc -l` |
| 128 |
|
| 129 |
(( debug == 1 )) && echo counting selfsigned |
| 130 |
selfsigned=`grep '18 (self signed certificate)$' *.ssl | wc -l` |
| 131 |
|
| 132 |
(( debug == 1 )) && echo counting selfchain |
| 133 |
selfchain=`grep '19 (self signed certificate in certificate chain)$' *.ssl | wc -l` |
| 134 |
|
| 135 |
(( debug == 1 )) && echo counting untrusted |
| 136 |
untrusted=`grep '20 (unable to get local issuer certificate)$' *.ssl | wc -l` |
| 137 |
|
| 138 |
(( debug == 1 )) && echo counting firstinvalid |
| 139 |
invalid=`grep '21 (unable to verify the first certificate)$' *.ssl | wc -l` |
| 140 |
|
| 141 |
(( debug == 1 )) && echo counting purpose |
| 142 |
purpose=`grep '26 (unsupported certificate purpose)$' *.ssl | wc -l` |
| 143 |
|
| 144 |
(( debug == 1 )) && echo counting dane |
| 145 |
dane=`grep THIS-LOOKS-LIKE-DANE$ *.dane | wc -l` |
| 146 |
#notlsa=`grep notlsa$ *.dane | wc -l` |
| 147 |
#servfail=`grep servfail$ *.dane | wc -l` |
| 148 |
#timeout=`grep timeout$ *.dane | wc -l` |
| 149 |
|
| 150 |
(( debug == 1 )) && echo counting daneee and daneta |
| 151 |
daneee=`grep ^DANE *.dane.results | grep 'matched EE' | wc -l` |
| 152 |
daneta=`grep ^DANE *.dane.results | grep 'matched TA' | wc -l` |
| 153 |
#grep ^DANE *.results | grep -vE 'matched EE|matched TA' |
| 154 |
|
| 155 |
(( debug == 1 )) && echo counting STARTTLS |
| 156 |
#TOFIX |
| 157 |
#enforcetotal=`cat mx.unique*.starttls.enforce.dist | wc -l` |
| 158 |
enforcetotal2=`cat mx.unique*.starttls.enforce | wc -l` |
| 159 |
connectbaddns=`grep connect-bad-dns$ mx.unique*.starttls.enforce | wc -l` |
| 160 |
connectfailed=`grep connect-failed$ mx.unique*.starttls.enforce | wc -l` |
| 161 |
connect4xx=`grep connect-4xx$ mx.unique*.starttls.enforce | wc -l` |
| 162 |
connect5xx=`grep connect-5xx$ mx.unique*.starttls.enforce | wc -l` |
| 163 |
connectrefused=`grep connect-refused$ mx.unique*.starttls.enforce | wc -l` |
| 164 |
connectclosed=`grep connect-closed$ mx.unique*.starttls.enforce | wc -l` |
| 165 |
connecttimeout=`grep connect-timeout$ mx.unique*.starttls.enforce | wc -l` |
| 166 |
connectunknown=`grep connect-unknown$ mx.unique*.starttls.enforce | wc -l` |
| 167 |
ehlo2xxnostarttls=`grep ehlo-2xx-no-starttls$ mx.unique*.starttls.enforce | wc -l` |
| 168 |
ehlo5xx=`grep ehlo-5xx$ mx.unique*.starttls.enforce | wc -l` |
| 169 |
ehlo4xx=`grep ehlo-4xx$ mx.unique*.starttls.enforce | wc -l` |
| 170 |
ehlotimeout=`grep ehlo-timeout$ mx.unique*.starttls.enforce | wc -l` |
| 171 |
ehlounknown=`grep ehlo-unknown$ mx.unique*.starttls.enforce | wc -l` |
| 172 |
#sender2xx=`grep sender-2xx$ mx.unique*.starttls.enforce | wc -l` |
| 173 |
#sender5xx=`grep sender-5xx$ mx.unique*.starttls.enforce | wc -l` |
| 174 |
#sender4xx=`grep sender-4xx$ mx.unique*.starttls.enforce | wc -l` |
| 175 |
hastls=`grep -E '^250-STARTTLS|^250 STARTTLS' mx.unique*.starttls | wc -l` |
| 176 |
|
| 177 |
#we want |
| 178 |
#530 5.7.0 Must issue a STARTTLS command first |
| 179 |
#530 5.5.1 Invalid command: Must issue a STARTTLS command first |
| 180 |
#530 Must issue STARTTLS first. |
| 181 |
#430 4.7.0 Must issue a STARTTLS command first |
| 182 |
#grep -E '[[:digit:]]{3} 5\.7\.3 ' mx.unique*.starttls |
| 183 |
|
| 184 |
#exceptions |
| 185 |
#530 5.7.1 Client was not authenticated |
| 186 |
#530 5.7.3 Client was not authenticated |
| 187 |
#530 aws.besteffort.com ESMTP MailEnable Service, Version: 9.76-9.76- denied access at 01/22/20 13:32:04 |
| 188 |
|
| 189 |
must=`grep -E '^575 |^[[:digit:]]{3} 5\.7\.3 |^530 |^451 5\.7\.3 |^430 4\.7\.0 |^451 .*TLS.*|^550 AUTH TLS |^550 TLS ' mx.unique*.starttls | grep -vE ' 5\.7\.1 |530 5\.7\.3 |MailEnable' | wc -l` |
| 190 |
|
| 191 |
(( mxdown = connectbaddns + connectfailed + connect4xx + connect5xx + connectrefused + connectclosed + connecttimeout + connectunknown )) |
| 192 |
|
| 193 |
cd ../../../ |
| 194 |
|
| 195 |
(( debug == 1 )) && echo |
| 196 |
|
| 197 |
printf "IPREV PTRs\t\t\t%'.f\n" $ptrs |
| 198 |
#next versions will have 2nd-3rd-level domains: $domains |
| 199 |
printf "Deferenced domains\t\t%'.f\n" $domains |
| 200 |
printf "MX records\t\t\t%'.f\n" $mx |
| 201 |
echo |
| 202 |
|
| 203 |
printf "Total results for enforce check\t%'.f\n" $enforcetotal2 |
| 204 |
printf "Unreachable MXen\t\t%'.f\n" $mxdown |
| 205 |
printf "No STARTTLS\t\t\t%'.f\n" $ehlo2xxnostarttls |
| 206 |
#printf "Opportunistic STARTTLS\t\t%'.f\n" $sender2xx |
| 207 |
#printf "Enforced STARTTLS or 5xx\t%'.f\n" $sender5xx |
| 208 |
#printf "Enforced STARTTLS or 4xx\t%'.f\n" $sender4xx |
| 209 |
printf "Offers STARTTLS\t\t\t%'.f\n" $hastls |
| 210 |
printf "Enforces STARTTLS\t\t%'.f\n" $must |
| 211 |
echo |
| 212 |
|
| 213 |
printf "Trusted certificate chain\t%'.f (ok)\n" $trueok |
| 214 |
printf "Cipher is (NONE)\t\t%'.f (ok)\n" $fakeok |
| 215 |
printf "From the future\t\t\t%'.f (certificate is not yet valid)\n" $notyet |
| 216 |
printf "Expired\t\t\t\t%'.f (certificate has expired)\n" $expired |
| 217 |
printf "Self-signed\t\t\t%'.f (self signed certificate)\n" $selfsigned |
| 218 |
printf "Self-signed CA\t\t\t%'.f (self signed certificate in certificate chain)\n" $selfchain |
| 219 |
printf "Untrusted certificate chain\t%'.f (unable to get local issuer certificate)\n" $untrusted |
| 220 |
printf "Invalid certificate\t\t%'.f (unable to verify the first certificate)\n" $invalid |
| 221 |
printf "Wrong purpose certificate\t%'.f (unsupported certificate purpose)\n" $purpose |
| 222 |
printf "TLSA records\t\t\t%'.f\n" $dane |
| 223 |
printf "Valid PKIX/DANE-EE\t\t%'.f\n" $daneee |
| 224 |
printf "Valid PKIX/DANE-TA\t\t%'.f\n" $daneta |
| 225 |
echo |
| 226 |
|
| 227 |
typeset -F2 result |
| 228 |
(( result = mx * 100 / domains )) |
| 229 |
echo $result% of deferenced domains have an MX record |
| 230 |
unset result |
| 231 |
|
| 232 |
typeset -F2 result |
| 233 |
(( result = trueok * 100 / mx )) |
| 234 |
echo $result% of MX certificates are valid |
| 235 |
unset result |
| 236 |
|
| 237 |
typeset -F2 result |
| 238 |
(( result = fakeok * 100 / mx )) |
| 239 |
echo $result% of MX end-points do not offer STARTTLS |
| 240 |
unset result |
| 241 |
|
| 242 |
typeset -F2 result |
| 243 |
(( result = expired * 100 / mx )) |
| 244 |
echo $result% of MX certificates are expired |
| 245 |
unset result |
| 246 |
|
| 247 |
typeset -F2 result |
| 248 |
(( result = selfsigned * 100 / mx )) |
| 249 |
echo $result% of MX certificates are self-signed |
| 250 |
unset result |
| 251 |
|
| 252 |
typeset -F2 result |
| 253 |
(( result = untrusted * 100 / mx )) |
| 254 |
echo $result% of MX certificates are private |
| 255 |
unset result |
| 256 |
|
| 257 |
typeset -F2 result |
| 258 |
(( result = invalid * 100 / mx )) |
| 259 |
echo $result% of MX certificates are invalid |
| 260 |
unset result |
| 261 |
|
| 262 |
typeset -F2 result |
| 263 |
(( result = dane * 100 / mx )) |
| 264 |
echo $result% of MX end-points have a DANE record |
| 265 |
unset result |
| 266 |
|
| 267 |
typeset -F2 result |
| 268 |
(( result = ( daneee + daneta ) * 100 / mx )) |
| 269 |
echo $result% of MX end-points validating DANE \(trusted, private and self-signed\) |
| 270 |
unset result |
| 271 |
|
| 272 |
echo |
| 273 |
|