mirror of
				https://github.com/drwetter/testssl.sh.git
				synced 2025-10-31 22:05:26 +01:00 
			
		
		
		
	manually merged #728 (see #423), credits also to @seccubus. Unfortunately the unit tests don't make so much sense atm
This commit is contained in:
		
							
								
								
									
										236
									
								
								testssl.sh
									
									
									
									
									
								
							
							
						
						
									
										236
									
								
								testssl.sh
									
									
									
									
									
								
							| @@ -3521,6 +3521,7 @@ run_client_simulation() { | |||||||
|      local i=0 |      local i=0 | ||||||
|      local name tls proto cipher temp what_dh bits curve |      local name tls proto cipher temp what_dh bits curve | ||||||
|      local has_dh_bits using_sockets=true |      local has_dh_bits using_sockets=true | ||||||
|  |      local client_service | ||||||
|  |  | ||||||
|      # source the external file |      # source the external file | ||||||
|      . "$TESTSSL_INSTALL_DIR/etc/client_simulation.txt" 2>/dev/null |      . "$TESTSSL_INSTALL_DIR/etc/client_simulation.txt" 2>/dev/null | ||||||
| @@ -3529,14 +3530,18 @@ run_client_simulation() { | |||||||
|           return 1 |           return 1 | ||||||
|      fi |      fi | ||||||
|  |  | ||||||
|      #FIXME, see client_simulation branch which has to be merged |      "$SSL_NATIVE" && using_sockets=false | ||||||
|      if "$SSL_NATIVE" || [[ -n "$STARTTLS" ]]; then |  | ||||||
|           using_sockets=false |  | ||||||
|      fi |  | ||||||
|  |  | ||||||
|      # doesn't make sense for other services |      if [[ $SERVICE != "" ]];  then | ||||||
|      if [[ $SERVICE != "HTTP" ]];  then |           client_service="$SERVICE" | ||||||
|           return 0 |      else | ||||||
|  |           # Can we take the service from STARTTLS? | ||||||
|  |            if [[ -n "$STARTTLS_PROTOCOL" ]]; then | ||||||
|  |                client_service=$(toupper "${STARTTLS_PROTOCOL%s}")    # strip trailing 's' in ftp(s), smtp(s), pop3(s), etc | ||||||
|  |           else | ||||||
|  |                outln "Could not determine which protocol was started, only simulating generic clients." | ||||||
|  |                client_service="undetermined" | ||||||
|  |           fi | ||||||
|      fi |      fi | ||||||
|  |  | ||||||
|      outln |      outln | ||||||
| @@ -3550,7 +3555,7 @@ run_client_simulation() { | |||||||
|      outln |      outln | ||||||
|  |  | ||||||
|      debugme tmln_out |      debugme tmln_out | ||||||
|       |  | ||||||
|      if "$WIDE"; then |      if "$WIDE"; then | ||||||
|           if [[ "$DISPLAY_CIPHERNAMES" =~ openssl ]]; then |           if [[ "$DISPLAY_CIPHERNAMES" =~ openssl ]]; then | ||||||
|                out " Browser                          Protocol  Cipher Suite Name (OpenSSL)      " |                out " Browser                          Protocol  Cipher Suite Name (OpenSSL)      " | ||||||
| @@ -3567,116 +3572,121 @@ run_client_simulation() { | |||||||
|           outln |           outln | ||||||
|      fi |      fi | ||||||
|      for name in "${short[@]}"; do |      for name in "${short[@]}"; do | ||||||
|           out " $(printf -- "%-33s" "${names[i]}")" |           if ${current[i]} ; then | ||||||
|           if "$using_sockets" && [[ -n "${handshakebytes[i]}" ]]; then |                # for ANY we test this service or if the service we determined from STARTTLS matches | ||||||
|                client_simulation_sockets "${handshakebytes[i]}" |                if [[ "${service[i]}" == "ANY" ]] || grep -q "$client_service" <<< "${service[i]}"; then | ||||||
|                sclient_success=$? |                     out " $(printf -- "%-33s" "${names[i]}")" | ||||||
|                if [[ $sclient_success -eq 0 ]]; then |                     if "$using_sockets" && [[ -n "${handshakebytes[i]}" ]]; then | ||||||
|                     if [[ "0x${DETECTED_TLS_VERSION}" -lt ${lowest_protocol[i]} ]] || \ |                          client_simulation_sockets "${handshakebytes[i]}" | ||||||
|                        [[ "0x${DETECTED_TLS_VERSION}" -gt ${highest_protocol[i]} ]]; then |  | ||||||
|                          sclient_success=1 |  | ||||||
|                     fi |  | ||||||
|                     [[ $sclient_success -eq 0 ]] && cp "$TEMPDIR/$NODEIP.parse_tls_serverhello.txt" $TMPFILE >$ERRFILE |  | ||||||
|                fi |  | ||||||
|           else |  | ||||||
|                ! "$HAS_NO_SSL2" && protos[i]="$(sed 's/-no_ssl2//' <<< "${protos[i]}")" |  | ||||||
|                debugme echo "$OPENSSL s_client -cipher ${ciphers[i]} ${protos[i]} $STARTTLS $BUGS $PROXY -connect $NODEIP:$PORT ${sni[i]}  </dev/null" |  | ||||||
|                $OPENSSL s_client -cipher ${ciphers[i]} ${protos[i]} $STARTTLS $BUGS $PROXY -connect $NODEIP:$PORT ${sni[i]}  </dev/null >$TMPFILE 2>$ERRFILE |  | ||||||
|                sclient_connect_successful $? $TMPFILE |  | ||||||
|                sclient_success=$? |  | ||||||
|           fi |  | ||||||
|           if [[ $sclient_success -eq 0 ]]; then |  | ||||||
|                # If an ephemeral DH key was used, check that the number of bits is within range. |  | ||||||
|                temp=$(awk -F': ' '/^Server Temp Key/ { print $2 }' "$TMPFILE")        # extract line |  | ||||||
|                what_dh=$(awk -F',' '{ print $1 }' <<< $temp) |  | ||||||
|                bits=$(awk -F',' '{ print $3 }' <<< $temp) |  | ||||||
|                if grep -q bits <<< $bits; then |  | ||||||
|                     curve="$(strip_spaces "$(awk -F',' '{ print $2 }' <<< $temp)")" |  | ||||||
|                else |  | ||||||
|                     curve="" |  | ||||||
|                     bits=$(awk -F',' '{ print $2 }' <<< $temp) |  | ||||||
|                fi |  | ||||||
|                bits="${bits/bits/}" |  | ||||||
|                bits="${bits// /}" |  | ||||||
|                if [[ "$what_dh" == "X25519" ]] || [[ "$what_dh" == "X448" ]]; then |  | ||||||
|                     curve="$what_dh" |  | ||||||
|                     what_dh="ECDH" |  | ||||||
|                fi |  | ||||||
|                if [[ "$what_dh" == "DH" ]]; then |  | ||||||
|                     [[ ${minDhBits[i]} -ne -1 ]] && [[ $bits -lt ${minDhBits[i]} ]] && sclient_success=1 |  | ||||||
|                     [[ ${maxDhBits[i]} -ne -1 ]] && [[ $bits -gt ${maxDhBits[i]} ]] && sclient_success=1 |  | ||||||
|                fi |  | ||||||
|           fi |  | ||||||
|           if [[ $sclient_success -ne 0 ]]; then |  | ||||||
|                outln "No connection" |  | ||||||
|                fileout "client_${short[i]}" "INFO" "$(strip_spaces "${names[i]}") client simulation: No connection" |  | ||||||
|           else |  | ||||||
|                proto=$(get_protocol $TMPFILE) |  | ||||||
|                # hack: |  | ||||||
|                [[ "$proto" == TLSv1 ]] && proto="TLSv1.0" |  | ||||||
|                [[ "$proto" == SSLv3 ]] && proto="SSLv3  " |  | ||||||
|                if [[ "$proto" == TLSv1.2 ]] && ( ! "$using_sockets" || [[ -z "${handshakebytes[i]}" ]] ); then |  | ||||||
|                     # OpenSSL reports TLS1.2 even if the connection is TLS1.1 or TLS1.0. Need to figure out which one it is... |  | ||||||
|                     for tls in ${tlsvers[i]}; do |  | ||||||
|                          debugme echo "$OPENSSL s_client $tls -cipher ${ciphers[i]} ${protos[i]} $STARTTLS $BUGS $PROXY -connect $NODEIP:$PORT ${sni[i]}  </dev/null" |  | ||||||
|                          $OPENSSL s_client $tls -cipher ${ciphers[i]} ${protos[i]} $STARTTLS $BUGS $PROXY -connect $NODEIP:$PORT ${sni[i]}  </dev/null >$TMPFILE 2>$ERRFILE |  | ||||||
|                          sclient_connect_successful $? $TMPFILE |  | ||||||
|                          sclient_success=$? |                          sclient_success=$? | ||||||
|                          if [[ $sclient_success -eq 0 ]]; then |                          if [[ $sclient_success -eq 0 ]]; then | ||||||
|                               case "$tls" in |                               if [[ "0x${DETECTED_TLS_VERSION}" -lt ${lowest_protocol[i]} ]] || \ | ||||||
|                                    "-tls1_2") |                                  [[ "0x${DETECTED_TLS_VERSION}" -gt ${highest_protocol[i]} ]]; then | ||||||
|                                         break |                                    sclient_success=1 | ||||||
|                                         ;; |                               fi | ||||||
|                                    "-tls1_1") |                               [[ $sclient_success -eq 0 ]] && cp "$TEMPDIR/$NODEIP.parse_tls_serverhello.txt" $TMPFILE >$ERRFILE | ||||||
|                                         proto="TLSv1.1" |  | ||||||
|                                         break |  | ||||||
|                                         ;; |  | ||||||
|                                    "-tls1") |  | ||||||
|                                         proto="TLSv1.0" |  | ||||||
|                                         break |  | ||||||
|                                         ;; |  | ||||||
|                               esac |  | ||||||
|                          fi |                          fi | ||||||
|                     done |  | ||||||
|                fi |  | ||||||
|                cipher=$(get_cipher $TMPFILE) |  | ||||||
|                if [[ "$DISPLAY_CIPHERNAMES" =~ openssl ]] && ( [[ "$cipher" == TLS_* ]] || [[ "$cipher" == SSL_* ]] ); then |  | ||||||
|                     cipher="$(rfc2openssl "$cipher")" |  | ||||||
|                     [[ -z "$cipher" ]] && cipher=$(get_cipher $TMPFILE) |  | ||||||
|                elif [[ "$DISPLAY_CIPHERNAMES" =~ rfc ]] && [[ "$cipher" != TLS_* ]] && [[ "$cipher" != SSL_* ]]; then |  | ||||||
|                     cipher="$(openssl2rfc "$cipher")" |  | ||||||
|                     [[ -z "$cipher" ]] && cipher=$(get_cipher $TMPFILE) |  | ||||||
|                fi |  | ||||||
|                if ! "$WIDE"; then |  | ||||||
|                     out "$proto $cipher" |  | ||||||
|                elif [[ "$DISPLAY_CIPHERNAMES" =~ openssl ]]; then |  | ||||||
|                     out "$(printf -- "%-7s   %-33s" "$proto" "$cipher")" |  | ||||||
|                else |  | ||||||
|                     out "$(printf -- "%-7s   %-49s" "$proto" "$cipher")" |  | ||||||
|                fi |  | ||||||
|                if ! "$WIDE"; then |  | ||||||
|                     "$using_sockets" && [[ -n "${handshakebytes[i]}" ]] && has_dh_bits=$HAS_DH_BITS && HAS_DH_BITS=true |  | ||||||
|                     "$HAS_DH_BITS" && read_dhbits_from_file $TMPFILE |  | ||||||
|                     "$using_sockets" && [[ -n "${handshakebytes[i]}" ]] && HAS_DH_BITS=$has_dh_bits |  | ||||||
|                elif [[ -n "$what_dh" ]]; then |  | ||||||
|                     [[ -n "$curve" ]] && curve="($curve)" |  | ||||||
|                     if [[ "$what_dh" == "ECDH" ]]; then |  | ||||||
|                          pr_ecdh_quality "$bits" "$(printf -- "%-12s" "$bits bit $what_dh") $curve" |  | ||||||
|                     else |                     else | ||||||
|                          pr_dh_quality "$bits" "$(printf -- "%-12s" "$bits bit $what_dh") $curve" |                          ! "$HAS_NO_SSL2" && protos[i]="$(sed 's/-no_ssl2//' <<< "${protos[i]}")" | ||||||
|  |                          debugme echo "$OPENSSL s_client -cipher ${ciphers[i]} ${protos[i]} $STARTTLS $BUGS $PROXY -connect $NODEIP:$PORT ${sni[i]}  </dev/null" | ||||||
|  |                          $OPENSSL s_client -cipher ${ciphers[i]} ${protos[i]} $STARTTLS $BUGS $PROXY -connect $NODEIP:$PORT ${sni[i]}  </dev/null >$TMPFILE 2>$ERRFILE | ||||||
|  |                          sclient_connect_successful $? $TMPFILE | ||||||
|  |                          sclient_success=$? | ||||||
|                     fi |                     fi | ||||||
|                elif "$HAS_DH_BITS" || ( "$using_sockets" && [[ -n "${handshakebytes[i]}" ]] ); then |                     if [[ $sclient_success -eq 0 ]]; then | ||||||
|                     out "No FS" |                          # If an ephemeral DH key was used, check that the number of bits is within range. | ||||||
|                fi |                          temp=$(awk -F': ' '/^Server Temp Key/ { print $2 }' "$TMPFILE")        # extract line | ||||||
|                outln |                          what_dh=$(awk -F',' '{ print $1 }' <<< $temp) | ||||||
|                if [[ -n "${warning[i]}" ]]; then |                          bits=$(awk -F',' '{ print $3 }' <<< $temp) | ||||||
|                     out "                            " |                          if grep -q bits <<< $bits; then | ||||||
|                     outln "${warning[i]}" |                               curve="$(strip_spaces "$(awk -F',' '{ print $2 }' <<< $temp)")" | ||||||
|                fi |                          else | ||||||
|                fileout "client_${short[i]}" "INFO" \ |                               curve="" | ||||||
|                     "$(strip_spaces "${names[i]}") client simulation:  $proto $cipher   ${warning[i]}" |                               bits=$(awk -F',' '{ print $2 }' <<< $temp) | ||||||
|                debugme cat $TMPFILE |                          fi | ||||||
|           fi |                          bits="${bits/bits/}" | ||||||
|  |                          bits="${bits// /}" | ||||||
|  |                          if [[ "$what_dh" == "X25519" ]] || [[ "$what_dh" == "X448" ]]; then | ||||||
|  |                               curve="$what_dh" | ||||||
|  |                               what_dh="ECDH" | ||||||
|  |                          fi | ||||||
|  |                          if [[ "$what_dh" == "DH" ]]; then | ||||||
|  |                               [[ ${minDhBits[i]} -ne -1 ]] && [[ $bits -lt ${minDhBits[i]} ]] && sclient_success=1 | ||||||
|  |                               [[ ${maxDhBits[i]} -ne -1 ]] && [[ $bits -gt ${maxDhBits[i]} ]] && sclient_success=1 | ||||||
|  |                          fi | ||||||
|  |                     fi | ||||||
|  |                     if [[ $sclient_success -ne 0 ]]; then | ||||||
|  |                          outln "No connection" | ||||||
|  |                          fileout "client_${short[i]}" "INFO" "$(strip_spaces "${names[i]}") client simulation: No connection" | ||||||
|  |                     else | ||||||
|  |                          proto=$(get_protocol $TMPFILE) | ||||||
|  |                          # hack: | ||||||
|  |                          [[ "$proto" == TLSv1 ]] && proto="TLSv1.0" | ||||||
|  |                          [[ "$proto" == SSLv3 ]] && proto="SSLv3  " | ||||||
|  |                          if [[ "$proto" == TLSv1.2 ]] && ( ! "$using_sockets" || [[ -z "${handshakebytes[i]}" ]] ); then | ||||||
|  |                               # OpenSSL reports TLS1.2 even if the connection is TLS1.1 or TLS1.0. Need to figure out which one it is... | ||||||
|  |                               for tls in ${tlsvers[i]}; do | ||||||
|  |                                    debugme echo "$OPENSSL s_client $tls -cipher ${ciphers[i]} ${protos[i]} $STARTTLS $BUGS $PROXY -connect $NODEIP:$PORT ${sni[i]}  </dev/null" | ||||||
|  |                                    $OPENSSL s_client $tls -cipher ${ciphers[i]} ${protos[i]} $STARTTLS $BUGS $PROXY -connect $NODEIP:$PORT ${sni[i]}  </dev/null >$TMPFILE 2>$ERRFILE | ||||||
|  |                                    sclient_connect_successful $? $TMPFILE | ||||||
|  |                                    sclient_success=$? | ||||||
|  |                                    if [[ $sclient_success -eq 0 ]]; then | ||||||
|  |                                         case "$tls" in | ||||||
|  |                                              "-tls1_2") | ||||||
|  |                                                   break | ||||||
|  |                                                   ;; | ||||||
|  |                                              "-tls1_1") | ||||||
|  |                                                   proto="TLSv1.1" | ||||||
|  |                                                   break | ||||||
|  |                                                   ;; | ||||||
|  |                                              "-tls1") | ||||||
|  |                                                   proto="TLSv1.0" | ||||||
|  |                                                   break | ||||||
|  |                                                   ;; | ||||||
|  |                                         esac | ||||||
|  |                                    fi | ||||||
|  |                               done | ||||||
|  |                          fi | ||||||
|  |                          cipher=$(get_cipher $TMPFILE) | ||||||
|  |                          if [[ "$DISPLAY_CIPHERNAMES" =~ openssl ]] && ( [[ "$cipher" == TLS_* ]] || [[ "$cipher" == SSL_* ]] ); then | ||||||
|  |                               cipher="$(rfc2openssl "$cipher")" | ||||||
|  |                               [[ -z "$cipher" ]] && cipher=$(get_cipher $TMPFILE) | ||||||
|  |                          elif [[ "$DISPLAY_CIPHERNAMES" =~ rfc ]] && [[ "$cipher" != TLS_* ]] && [[ "$cipher" != SSL_* ]]; then | ||||||
|  |                               cipher="$(openssl2rfc "$cipher")" | ||||||
|  |                               [[ -z "$cipher" ]] && cipher=$(get_cipher $TMPFILE) | ||||||
|  |                          fi | ||||||
|  |                          if ! "$WIDE"; then | ||||||
|  |                               out "$proto $cipher" | ||||||
|  |                          elif [[ "$DISPLAY_CIPHERNAMES" =~ openssl ]]; then | ||||||
|  |                               out "$(printf -- "%-7s   %-33s" "$proto" "$cipher")" | ||||||
|  |                          else | ||||||
|  |                               out "$(printf -- "%-7s   %-49s" "$proto" "$cipher")" | ||||||
|  |                          fi | ||||||
|  |                          if ! "$WIDE"; then | ||||||
|  |                               "$using_sockets" && [[ -n "${handshakebytes[i]}" ]] && has_dh_bits=$HAS_DH_BITS && HAS_DH_BITS=true | ||||||
|  |                               "$HAS_DH_BITS" && read_dhbits_from_file $TMPFILE | ||||||
|  |                               "$using_sockets" && [[ -n "${handshakebytes[i]}" ]] && HAS_DH_BITS=$has_dh_bits | ||||||
|  |                          elif [[ -n "$what_dh" ]]; then | ||||||
|  |                               [[ -n "$curve" ]] && curve="($curve)" | ||||||
|  |                               if [[ "$what_dh" == "ECDH" ]]; then | ||||||
|  |                                    pr_ecdh_quality "$bits" "$(printf -- "%-12s" "$bits bit $what_dh") $curve" | ||||||
|  |                               else | ||||||
|  |                                    pr_dh_quality "$bits" "$(printf -- "%-12s" "$bits bit $what_dh") $curve" | ||||||
|  |                               fi | ||||||
|  |                          elif "$HAS_DH_BITS" || ( "$using_sockets" && [[ -n "${handshakebytes[i]}" ]] ); then | ||||||
|  |                               out "No FS" | ||||||
|  |                          fi | ||||||
|  |                          outln | ||||||
|  |                          if [[ -n "${warning[i]}" ]]; then | ||||||
|  |                               out "                            " | ||||||
|  |                               outln "${warning[i]}" | ||||||
|  |                          fi | ||||||
|  |                          fileout "client_${short[i]}" "INFO" \ | ||||||
|  |                               "$(strip_spaces "${names[i]}") client simulation:  $proto $cipher   ${warning[i]}" | ||||||
|  |                          debugme cat $TMPFILE | ||||||
|  |                     fi | ||||||
|  |                fi   # correct service? | ||||||
|  |           fi   #current? | ||||||
|           i=$((i+1)) |           i=$((i+1)) | ||||||
|      done |      done | ||||||
|      tmpfile_handle $FUNCNAME.txt |      tmpfile_handle $FUNCNAME.txt | ||||||
|   | |||||||
							
								
								
									
										341
									
								
								utils/update_client_sim_data.pl
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										341
									
								
								utils/update_client_sim_data.pl
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,341 @@ | |||||||
|  | #!/usr/bin/perl | ||||||
|  |  | ||||||
|  | use strict; | ||||||
|  | use Data::Dumper; | ||||||
|  | use JSON; | ||||||
|  |  | ||||||
|  | my $namelength = 30; | ||||||
|  |  | ||||||
|  | my @spec; | ||||||
|  | my %ciphers; | ||||||
|  | foreach my $line ( split /\n/, `../bin/openssl.Linux.x86_64 ciphers -V 'ALL:COMPLEMENTOFALL:\@STRENGTH'`) { | ||||||
|  | 	my @fields = split /\s+/, $line; | ||||||
|  | 	my $hex = ""; | ||||||
|  | 	foreach my $byte ( split /,/, $fields[1] ) { | ||||||
|  | 		$byte = lc $byte; | ||||||
|  | 		$byte =~ s/^0x//; | ||||||
|  | 		$hex .= $byte; | ||||||
|  | 	} | ||||||
|  | 	$hex =~ s/^0+//; | ||||||
|  | 	$ciphers{hex "0x$hex"} = $fields[3]; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # Get the data | ||||||
|  | my $json = `curl 'https://api.dev.ssllabs.com/api/v3/getClients'`; | ||||||
|  | my $ssllabs = decode_json($json); | ||||||
|  |  | ||||||
|  | my %sims; | ||||||
|  | foreach my $client ( @$ssllabs ) { | ||||||
|  | 	# Shorts | ||||||
|  | 	my $has_matched = 1; | ||||||
|  | 	my $shortname = "$client->{name}_$client->{version}"; | ||||||
|  | 	$shortname =~ s/ /_/g; | ||||||
|  | 	$shortname =~ s/\.//g; | ||||||
|  | 	$shortname .= "_$client->{platform}" if exists $client->{platform}; | ||||||
|  | 	$shortname =~ s/[ \.]//g; | ||||||
|  | 	$shortname = lc($shortname); | ||||||
|  |  | ||||||
|  | 	# Deduplicate | ||||||
|  | 	if ( ! exists $sims{$shortname} || $sims{$shortname}->{id} < $client->{id} ) { | ||||||
|  | 		my $sim = {}; | ||||||
|  | 		$sims{$shortname} = $sim; | ||||||
|  | 		$sim->{shortname} = "short+=(\"$shortname\")"; | ||||||
|  |  | ||||||
|  | 		# Names | ||||||
|  | 		my $name = "$client->{name} $client->{version}"; | ||||||
|  | 		$name .= " $client->{platform}" if exists $client->{platform}; | ||||||
|  | 		# Get first namelength characters only | ||||||
|  | 		$name = substr($name . "" x $namelength,0,$namelength); | ||||||
|  | 		$sim->{name} = "names+=(\"$name\")"; | ||||||
|  |  | ||||||
|  | 		# Ciphers | ||||||
|  | 		my @ciphers = (); | ||||||
|  | 		foreach my $suite ( @{$client->{suiteIds}} ) { | ||||||
|  | 			if ( exists $ciphers{$suite} ) { | ||||||
|  | 				push @ciphers, $ciphers{$suite}; } | ||||||
|  | 			elsif ( $suite == "255" ) { | ||||||
|  | 				# no openssl name for this: | ||||||
|  | 				if ( $has_matched ) { | ||||||
|  | 					print "Ignored: \"$shortname\" has" ; | ||||||
|  | 					$has_matched = 0; | ||||||
|  | 				} | ||||||
|  | 				print " \"0xFF\""; } | ||||||
|  | 			elsif ( $suite == "65279" ) { | ||||||
|  | 				# SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA | ||||||
|  | 				if ( $has_matched ) { | ||||||
|  | 					print "Ignored: \"$shortname\" has" ; | ||||||
|  | 					$has_matched = 0; | ||||||
|  | 				} | ||||||
|  | 				print " \"0xFEFF\""; } | ||||||
|  | 			elsif ( $suite == "52392" ) { | ||||||
|  | 				push @ciphers, "ECDHE-RSA-CHACHA20-POLY1305"; } | ||||||
|  | 			elsif ( $suite == "52393" ) { | ||||||
|  | 				push @ciphers, "ECDHE-ECDSA-CHACHA20-POLY1305"; } | ||||||
|  | 			elsif ( $suite == "52394" ) { | ||||||
|  | 				push @ciphers, "DHE-RSA-CHACHA20-POLY1305"; } | ||||||
|  | 			else { | ||||||
|  | 				print "ALERT: "; | ||||||
|  | 				if ( $has_matched ) { | ||||||
|  | 					print " \"$shortname\" has "; | ||||||
|  | 					$has_matched = 0; | ||||||
|  | 				} | ||||||
|  | 				print "$suite. Please FIXME "; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		print "\n" if ! $has_matched ; | ||||||
|  | 		$sim->{ciphers} = "ciphers+=(\"" . (join ":", @ciphers) . "\")"; | ||||||
|  |  | ||||||
|  | 		# SNI | ||||||
|  | 		if ( exists $client->{supportsSni} && $client->{supportsSni} ) { | ||||||
|  | 			$sim->{sni} = "sni+=(\"\$SNI\")"; | ||||||
|  | 		} else { | ||||||
|  | 			$sim->{sni} = "sni+=(\"\")"; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		# warning (if needed) | ||||||
|  | 		$sim->{warning} = "warning+=(\"\")"; | ||||||
|  |  | ||||||
|  | 		# Handshake | ||||||
|  | 		if ( exists $client->{hexHandshakeBytes} ) { | ||||||
|  | 			$sim->{handshakebytes} = "handshakebytes+=(\"$client->{hexHandshakeBytes}\")"; | ||||||
|  | 		} else { | ||||||
|  | 			$sim->{handshakebytes} = "handshakebytes+=(\"\")"; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		# protos | ||||||
|  | 		my @proto_flags = (); | ||||||
|  | 		my @tls_flags = (); | ||||||
|  | 		# Figure out if we need to support sslv2 | ||||||
|  | 		if ( $client->{lowestProtocol} < 768 && $client->{highestProtocol} >= 512 ) { | ||||||
|  | 			# 512 = 0x200 = sslv2 | ||||||
|  | 			# 768 = 0x300 = sslv3 | ||||||
|  | 			push @proto_flags, "-ssl2"; | ||||||
|  | 		} | ||||||
|  | 		# Do we need to support SSL3? | ||||||
|  | 		if ( $client->{lowestProtocol} <= 768 && $client->{highestProtocol} >= 768 ) { | ||||||
|  | 			# 768 = 0x300 = sslv3 | ||||||
|  | 			push @proto_flags, "-ssl3"; | ||||||
|  | 		} | ||||||
|  | 		# Do we need to support TLS 1.0? | ||||||
|  | 		if ( $client->{lowestProtocol} <= 769 && $client->{highestProtocol} >= 769 ) { | ||||||
|  | 			# 769 = 0x301 = tls1.0 | ||||||
|  | 			push @proto_flags, "-tls1"; | ||||||
|  | 		} | ||||||
|  | 		# Do we need to support TLS 1.1? | ||||||
|  | 		if ( $client->{lowestProtocol} <= 770 && $client->{highestProtocol} >= 770 ) { | ||||||
|  | 			# 770 = 0x302 = tls1.1 | ||||||
|  | 			push @proto_flags, "-tls1_1"; | ||||||
|  | 		} | ||||||
|  | 		# Do we need to support TLS 1.2? | ||||||
|  | 		if ( $client->{lowestProtocol} <= 771 && $client->{highestProtocol} >= 771 ) { | ||||||
|  | 			# 771 = 0x303 = tls1.2 | ||||||
|  | 			push @proto_flags, "-tls1_2"; | ||||||
|  | 		} | ||||||
|  | 		$sim->{protos} = "protos+=(\"" . (join " ", reverse @proto_flags) . "\")"; | ||||||
|  | 		$sim->{lowestProtocol} = sprintf("lowest_protocol+=(\"0x%04x\")", $client->{lowestProtocol}); | ||||||
|  | 		$sim->{highestProtocol} = sprintf("highest_protocol+=(\"0x%04x\")", $client->{highestProtocol}); | ||||||
|  |  | ||||||
|  | 		if ( lc($client->{name}) eq "java" || lc($client->{name}) eq "openssl" ) { | ||||||
|  | 			# Java and OpenSSL are generic clients | ||||||
|  | 			$sim->{service} =  "service+=(\"ANY\")"; | ||||||
|  | 		} elsif ( $shortname =~ /^apple_ats/ ) { | ||||||
|  | 			# Apple ATS is HTTP(s) only | ||||||
|  | 			$sim->{service} = "service+=(\"HTTP\")"; | ||||||
|  | 		} else { | ||||||
|  | 			# All others are HTTP(s)/FTP only | ||||||
|  | 			$sim->{service} = "service+=(\"HTTP,FTP\")"; | ||||||
|  | 		} | ||||||
|  |  | ||||||
|  | 		# Bit size limitations | ||||||
|  | 		$sim->{minDhBits} = "minDhBits+=($client->{minDhBits})"; | ||||||
|  | 		$sim->{maxDhBits} = "maxDhBits+=($client->{maxDhBits})"; | ||||||
|  | 		$sim->{minRsaBits} = "minRsaBits+=($client->{minRsaBits})"; | ||||||
|  | 		$sim->{maxRsaBits} = "maxRsaBits+=($client->{maxRsaBits})"; | ||||||
|  | 		$sim->{minEcdsaBits} = "minEcdsaBits+=($client->{minEcdsaBits})"; | ||||||
|  | 		if ( defined $client->{requiresSha2} && $client->{requiresSha2} ) { | ||||||
|  | 			$sim->{requiresSha2} = "requiresSha2+=(true)"; | ||||||
|  | 		} else { | ||||||
|  | 			$sim->{requiresSha2} = "requiresSha2+=(false)"; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | # | ||||||
|  | # This is where we maintain our own clients | ||||||
|  | my $sim = {}; | ||||||
|  | #$sim->{name} = "names+=(\"Mail iOS 9.3.2                \")"; | ||||||
|  | #$sim->{shortname} = "short+=(\"mail_ios_932\")"; | ||||||
|  | #$sim->{ciphers} = "ciphers+=(\"ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:EDH-RSA-DES-CBC3-SHA:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:ECDHE-ECDSA-RC4-SHA:ECDHE-RSA-RC4-SHA:RC4-SHA:RC4-MD5\")"; | ||||||
|  | #$sim->{sni} = "sni+=(\"\$SNI\")"; | ||||||
|  | #$sim->{warning} = "warning+=(\"\")"; | ||||||
|  | #$sim->{handshakebytes} = "handshakebytes+=(\"16030100bb010000b703015767e6ae46f9abf3138e26a9f9880f9697bf3387f7eff709db1fa220e692d80420fb04b0979bae1664e11ef172d4dfba15af59dd200b7831992a35c73cde9efed9003200ffc024c023c00ac009c008c028c027c014c013c012006b0067003900330016003d003c0035002f000ac007c011000500040100003c000000190017000014696d61702e73656374696f6e7a65726f2e6f7267000a00080006001700180019000b0002010000050005010000000000120000\")"; | ||||||
|  | #$sim->{protos} = "protos+=(\"#-tls1_1 -tls1\")"; | ||||||
|  | #$sim->{lowestProtocol} = "lowest_protocol+=(\"0x0300\")"; | ||||||
|  | #$sim->{highestProtocol} = "highest_protocol+=(\"0x0301\")"; | ||||||
|  | #$sim->{service} = "service+=(\"SMTP,POP,IMAP\")"; | ||||||
|  | #$sim->{minDhBits} = "minDhBits+=(-1)"; | ||||||
|  | #$sim->{maxDhBits} = "maxDhBits+=(-1)"; | ||||||
|  | #$sim->{minRsaBits} = "minRsaBits+=(-1)"; | ||||||
|  | #$sim->{maxRsaBits} = "maxRsaBits+=(-1)"; | ||||||
|  | #$sim->{minEcdsaBits} = "minEcdsaBits+=(-1)"; | ||||||
|  | #$sim->{requiresSha2} = "requiresSha2+=(false)"; | ||||||
|  | # | ||||||
|  | #$sim->{name} = "names+=(\"Mail OSX 10.11.15             \")"; | ||||||
|  | #$sim->{shortname} = "short+=(\"mail_osx_101115\")"; | ||||||
|  | #$sim->{ciphers} = "ciphers+=(\"ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-DES-CBC3-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES128-SHA256:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:EDH-RSA-DES-CBC3-SHA:AES256-SHA256:AES128-SHA256:AES256-SHA:AES128-SHA:DES-CBC3-SHA:ECDHE-ECDSA-RC4-SHA:ECDHE-RSA-RC4-SHA:RC4-SHA:RC4-MD5\")"; | ||||||
|  | #$sim->{sni} = "sni+=(\"\$SNI\")"; | ||||||
|  | #$sim->{warning} = "warning+=(\"\")"; | ||||||
|  | #$sim->{handshakebytes} = "handshakebytes+=(\"16030100940100009003015770e928499e82df2eb7477200e2a828d9fa4109514385bd1602df44aaf2b0f400003200ffc024c023c00ac009c008c028c027c014c013c012006b0067003900330016003d003c0035002f000ac007c011000500040100003500000012001000000d3137382e3233372e33342e3932000a00080006001700180019000b0002010000050005010000000000120000\")"; | ||||||
|  | #$sim->{protos} = "protos+=(\"-tls1\")"; | ||||||
|  | #$sim->{lowestProtocol} = "lowest_protocol+=(\"0x0301\")"; | ||||||
|  | #$sim->{highestProtocol} = "highest_protocol+=(\"0x0301\")"; | ||||||
|  | #$sim->{service} = "service+=(\"SMTP,POP,IMAP\")"; | ||||||
|  | #$sim->{minDhBits} = "minDhBits+=(-1)"; | ||||||
|  | #$sim->{maxDhBits} = "maxDhBits+=(-1)"; | ||||||
|  | #$sim->{minRsaBits} = "minRsaBits+=(-1)"; | ||||||
|  | #$sim->{maxRsaBits} = "maxRsaBits+=(-1)"; | ||||||
|  | #$sim->{minEcdsaBits} = "minEcdsaBits+=(-1)"; | ||||||
|  | #$sim->{requiresSha2} = "requiresSha2+=(false)"; | ||||||
|  |  | ||||||
|  | $sim->{name} = "names+=(\"Thunderbird 45.1.1 OSX 10.11  \")"; | ||||||
|  | $sim->{shortname} = "short+=(\"thunderbird_45.1.1_osx_101115\")"; | ||||||
|  | $sim->{ciphers} = "ciphers+=(\"ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:AES128-SHA:AES256-SHA:DES-CBC3-SHA\")"; | ||||||
|  | $sim->{sni} = "sni+=(\"\$SNI\")"; | ||||||
|  | $sim->{warning} = "warning+=(\"\")"; | ||||||
|  | $sim->{handshakebytes} = "handshakebytes+=(\"160301009d010000990303c7c5b3ff80b3aa597c770c538b98ae34a94c9590ad8f947ba7bc28692061cb57000016c02bc02fc00ac009c013c01400330039002f0035000a0100005a0000001800160000136d78332e73656374696f6e7a65726f2e6f7267ff01000100000a00080006001700180019000b0002010000230000000500050100000000000d001600140401050106010201040305030603020304020202\")"; | ||||||
|  | $sim->{protos} = "protos+=(\"-tls1_2 -tls1_1 -tls1\")"; | ||||||
|  | $sim->{lowestProtocol} = "lowest_protocol+=(\"0x0301\")"; | ||||||
|  | $sim->{highestProtocol} = "highest_protocol+=(\"0x0303\")"; | ||||||
|  | $sim->{service} = "service+=(\"SMTP,POP,IMAP\")"; | ||||||
|  | $sim->{minDhBits} = "minDhBits+=(-1)"; | ||||||
|  | $sim->{maxDhBits} = "maxDhBits+=(-1)"; | ||||||
|  | $sim->{minRsaBits} = "minRsaBits+=(-1)"; | ||||||
|  | $sim->{maxRsaBits} = "maxRsaBits+=(-1)"; | ||||||
|  | $sim->{minEcdsaBits} = "minEcdsaBits+=(-1)"; | ||||||
|  | $sim->{requiresSha2} = "requiresSha2+=(false)"; | ||||||
|  |  | ||||||
|  | my %count; | ||||||
|  | foreach my $shortname ( reverse sort keys %sims ) { | ||||||
|  | 	if ( $shortname =~ /^baidu/ ) { | ||||||
|  | 		$count{baidu}++; | ||||||
|  | 		if ( $count{baidu} <= 1 ) { | ||||||
|  | 			$sims{$shortname}->{current} = "current+=(true)"; | ||||||
|  | 		} else { | ||||||
|  | 			$sims{$shortname}->{current} = "current+=(false)"; | ||||||
|  | 		} | ||||||
|  | 	} elsif ($shortname =~ /^bing/) { | ||||||
|  | 		$count{bing}++; | ||||||
|  | 		if ( $count{bing} <= 1 ) { | ||||||
|  | 			$sims{$shortname}->{current} = "current+=(true)"; | ||||||
|  | 		} else { | ||||||
|  | 			$sims{$shortname}->{current} = "current+=(false)"; | ||||||
|  | 		} | ||||||
|  | 	} elsif ($shortname =~ /^chrome/) { | ||||||
|  | 		$count{chrome}++; | ||||||
|  | 		if ( $count{chrome} <= 1 ) { | ||||||
|  | 			$sims{$shortname}->{current} = "current+=(true)"; | ||||||
|  | 		} else { | ||||||
|  | 			$sims{$shortname}->{current} = "current+=(false)"; | ||||||
|  | 		} | ||||||
|  | 	} elsif ($shortname =~ /^firefox/) { | ||||||
|  | 		# Latest version + ESR releases | ||||||
|  | 		if ( $shortname =~ /ESR/ ) { | ||||||
|  | 			$sims{$shortname}->{current} = "current+=(true)"; | ||||||
|  | 		} else { | ||||||
|  | 			$count{firefox}++; | ||||||
|  | 			if ( $count{firefox} <= 1 ) { | ||||||
|  | 				$sims{$shortname}->{current} = "current+=(true)"; | ||||||
|  | 			} else { | ||||||
|  | 				$sims{$shortname}->{current} = "current+=(false)"; | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 	} elsif ($shortname =~ /^googlebot/) { | ||||||
|  | 		$count{googlebot}++; | ||||||
|  | 		if ( $count{googlebot} <= 1 ) { | ||||||
|  | 			$sims{$shortname}->{current} = "current+=(true)"; | ||||||
|  | 		} else { | ||||||
|  | 			$sims{$shortname}->{current} = "current+=(false)"; | ||||||
|  | 		} | ||||||
|  | 	} elsif ($shortname =~ /^tor/) { | ||||||
|  | 		$count{tor}++; | ||||||
|  | 		if ( $count{tor} <= 1 ) { | ||||||
|  | 			$sims{$shortname}->{current} = "current+=(true)"; | ||||||
|  | 		} else { | ||||||
|  | 			$sims{$shortname}->{current} = "current+=(false)"; | ||||||
|  | 		} | ||||||
|  | 	} elsif ($shortname =~ /^yahoo/) { | ||||||
|  | 		$count{yahoo}++; | ||||||
|  | 		if ( $count{yahoo} <= 1 ) { | ||||||
|  | 			$sims{$shortname}->{current} = "current+=(true)"; | ||||||
|  | 		} else { | ||||||
|  | 			$sims{$shortname}->{current} = "current+=(false)"; | ||||||
|  | 		} | ||||||
|  | 	} elsif ($shortname =~ /^yandex/) { | ||||||
|  | 		$count{yandex}++; | ||||||
|  | 		if ( $count{yandex} <= 1 ) { | ||||||
|  | 			$sims{$shortname}->{current} = "current+=(true)"; | ||||||
|  | 		} else { | ||||||
|  | 			$sims{$shortname}->{current} = "current+=(false)"; | ||||||
|  | 		} | ||||||
|  | 	} elsif ($shortname =~ /^opera/) { | ||||||
|  | 		$count{opera}++; | ||||||
|  | 		if ( $count{opera} <= 1 ) { | ||||||
|  | 			$sims{$shortname}->{current} = "current+=(true)"; | ||||||
|  | 		} else { | ||||||
|  | 			$sims{$shortname}->{current} = "current+=(false)"; | ||||||
|  | 		} | ||||||
|  | 	} elsif ($shortname =~ /^java 7/) { | ||||||
|  | 		$count{java7}++; | ||||||
|  | 		if ( $count{java7} <= 1 ) { | ||||||
|  | 			$sims{$shortname}->{current} = "current+=(true)"; | ||||||
|  | 		} else { | ||||||
|  | 			$sims{$shortname}->{current} = "current+=(false)"; | ||||||
|  | 		} | ||||||
|  | 	} elsif ($shortname =~ /^java 8/) { | ||||||
|  | 		$count{java8}++; | ||||||
|  | 		if ( $count{java8} <= 1 ) { | ||||||
|  | 			$sims{$shortname}->{current} = "current+=(true)"; | ||||||
|  | 		} else { | ||||||
|  | 			$sims{$shortname}->{current} = "current+=(false)"; | ||||||
|  | 		} | ||||||
|  | 	} elsif ($shortname =~ /^java/) { | ||||||
|  | 		# Other/older versions of java aren't current | ||||||
|  | 		$sims{$shortname}->{current} = "current+=(false)"; | ||||||
|  | 	} elsif ($shortname =~ /^openssl/) { | ||||||
|  | 		$count{openssl}++; | ||||||
|  | 		if ( $count{openssl} <= 1 ) { | ||||||
|  | 			$sims{$shortname}->{current} = "current+=(true)"; | ||||||
|  | 		} else { | ||||||
|  | 			$sims{$shortname}->{current} = "current+=(false)"; | ||||||
|  | 		} | ||||||
|  | 	} elsif ($shortname =~ /^safari/) { | ||||||
|  | 		$count{safari}++; | ||||||
|  | 		if ( $count{safari} <= 2 ) { | ||||||
|  | 			$sims{$shortname}->{current} = "current+=(true)"; | ||||||
|  | 		} else { | ||||||
|  | 			$sims{$shortname}->{current} = "current+=(false)"; | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		# All versions are current | ||||||
|  | 		$sims{$shortname}->{current} = "current+=(true)"; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | open OUT, ">client-simulation-data.sh" or die "Unable to open client-simulation-data.sh"; | ||||||
|  | print OUT "#!/usr/bin/env bash | ||||||
|  |  | ||||||
|  | # This file contains client handshake data used in the run_client_simulation function | ||||||
|  | # Don't update this file by hand, but run util/update_client_sim_data.pl instead | ||||||
|  |  | ||||||
|  | # Most clients are taken from Qualys SSL Labs --- From: https://api.dev.ssllabs.com/api/v3/getClients | ||||||
|  | "; | ||||||
|  | foreach my $shortname ( sort keys %sims ) { | ||||||
|  | 	foreach my $k ( qw(name shortname ciphers sni warning handshakebytes protos lowestProtocol highestProtocol service | ||||||
|  | 		minDhBits maxDhBits minRsaBits maxRsaBits minEcdsaBits requiresSha2 current) ) { | ||||||
|  | 		print OUT "     $sims{$shortname}->{$k}\n"; | ||||||
|  | 	} | ||||||
|  | 	print OUT "\n"; | ||||||
|  | } | ||||||
|  | close OUT; | ||||||
|  |  | ||||||
|  | exit; | ||||||
							
								
								
									
										43
									
								
								utils/wireshark2ciphers.pl
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										43
									
								
								utils/wireshark2ciphers.pl
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,43 @@ | |||||||
|  | #!/usr/bin/perl | ||||||
|  |  | ||||||
|  | use strict; | ||||||
|  | use Data::Dumper; | ||||||
|  | use JSON; | ||||||
|  |  | ||||||
|  | my $namelength = 30; | ||||||
|  |  | ||||||
|  | # Get all ciphers first (sorry only works on 64 bit mac atm) | ||||||
|  | my @spec; | ||||||
|  | my %ciphers; | ||||||
|  | foreach my $line ( split /\n/, `bin/openssl.Darwin.x86_64 ciphers -V 'ALL:COMPLEMENTOFALL:\@STRENGTH'`) { | ||||||
|  | 	my @fields = split /\s+/, $line; | ||||||
|  | 	my $hex = ""; | ||||||
|  | 	foreach my $byte ( split /,/, $fields[1] ) { | ||||||
|  | 		$byte = lc $byte; | ||||||
|  | 		$byte =~ s/^0x//; | ||||||
|  | 		$hex .= $byte; | ||||||
|  | 	} | ||||||
|  | 	$hex =~ s/^0+//; | ||||||
|  | 	$ciphers{"0x$hex"} = $fields[3]; | ||||||
|  | } | ||||||
|  | #die Dumper \%ciphers; | ||||||
|  | #exit; | ||||||
|  |  | ||||||
|  | my @ciphers = (); | ||||||
|  | while (<>) { | ||||||
|  | 	if ( /^\s*Cipher Suite\:/ ) { | ||||||
|  | 		/\((0x[0-9a-f]+)\)\s*$/; | ||||||
|  | 		my $n = $1; | ||||||
|  | 		$n =~ s/0x0*/0x/; | ||||||
|  | 		if ( $n && exists $ciphers{$n} ) { | ||||||
|  | 			push @ciphers, $ciphers{$n}; | ||||||
|  | 		} else { | ||||||
|  | 			print STDERR "No matching cipher for: $n on line\n$_" | ||||||
|  | 		} | ||||||
|  | 	} else { | ||||||
|  | 		print STDERR "Ignoring line $_" | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  |  | ||||||
|  | print "\n\n" . join ":", @ciphers; | ||||||
|  | print "\n"; | ||||||
		Reference in New Issue
	
	Block a user
	 Dirk
					Dirk