Git Product home page Git Product logo

tls-scan's Introduction

Build Status Release Status

tls-scan

A program to scan TLS based servers and collect X.509 certificates, ciphers and related information. It produces results in JSON format. tls-scan is a single threaded asynchronous/event-based program (powered by libevent) capable of concurrently scan thousands of TLS servers. It can be combined with other tools such as GNU parallel to vertically scale in multi-core machines.

tls-scan helps developers and security engineers to track/test/debug certificates and TLS configurations of servers within their organization.

Features

  • Support for TLSv1.3
  • TLS and StartTLS protocol support: SMTP, IMAP, POP3, FTPS, SIEVE, NNTP, XMPP, LDAP, RDP, POSTGRES, MYSQL
  • Blazing fast - Can operate at scale with the ability to concurrently scan large number of servers (say scan IoT devices at scale)
  • Detect SSLv2, SSLv3, TLSv1, TLSv1.1, TLSv1.2, TLSv1.3 versions and ciphers
  • ALPN protocol id enumeration
  • Cipher and TLS version enumeration
  • Extract X.509 certificate fields from the target server and print it in JSON format
  • Certificate and host name verification checks
  • TLS compression checks
  • Session reuse tests
  • Certificate revocation checks with stapled OCSP response
  • Script friendly output - Can be combined with other tools to analyze the scan results
  • Detailed run time stats for tracking progress and performance/charts

This tool is primarily for collecting TLS cipher and X.509 certificate data. The scan output can be easily combined with related tools to identify TLS misconfigurations.

Installation

You may either use pre-built binary package or build from the source.

Pre-built Binary (x86_64)

Linux and OSX: https://github.com/prbinu/tls-scan/releases/latest

Build From Source

All you need is build-x86-64.sh (or build-arm64.sh for Linux Arm arch). This script pulls dependent packages - PeterMosmans openssl, libevent and GnuTLS, and build those from the scratch. Since the openssl we use is different from stock openssl, it is linked statically to tls-scan program. The build can take approximately twenty minutes to complete.

Build Pre-requisites :

On Ubuntu:

sudo apt-get update
sudo apt-get install make autoconf automake libtool pkg-config gcc unzip -y

Linux

git clone https://github.com/prbinu/tls-scan.git
cd tls-scan

x84_64

./build-x86-64.sh

The newly built tls-scan binary can be found at ./build-root/bin. build-x86-64.sh is a wrapper script that calls ./bootstrap.sh to build all dependent packages. bootstrap.sh also executes the autoreconf -i command to generate configure file. Subsequently it calles the standard ./configure, make && make install.

arm64

./build-arm64.sh

Test :

cd build-root/bin
./tls-scan --connect=yahoo.com --cacert=../etc/tls-scan/ca-bundle.crt --pretty

OSX

If you do not have the pre-requisite packages, you can easily install those packages by following the links below:

git clone https://github.com/prbinu/tls-scan.git
cd tls-scan
./build-x86-64.sh

The tls-scan binary can be found at ./build-root/bin. Another (easy) option is to use our Docker image to build and run tls-scan on OSX.

Running tls-scan on Mac Apple Silicon (Arm/M1/M2):

Currently no native build support, however you may run tls-scan binary using Rosetta2

Docker

Pre-requisite : Docker

Build : Copy the Dockerfile to your machine, and run it:

docker build -t tls-scan .

Test :

docker run --rm tls-scan --connect=example.com:443 --all --pretty

Example

./tls-scan -c search.yahoo.com --all --pretty
{
  "host": "search.yahoo.com",
  "ip": "208.71.45.12",
  "port": 443,
  "elapsedTime": 1600,
  "tlsVersion": "TLSv1.2",
  "cipher": "ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH     Au=RSA  Enc=AESGCM(128) Mac=AEAD",
  "tempPublicKeyAlg": "ECDH prime256v1",
  "tempPublicKeySize": 256,
  "secureRenego": true,
  "compression": "NONE",
  "expansion": "NONE",
  "sessionLifetimeHint": 100800,
  "tlsVersions": [
    "TLSv1",
    "TLSv1_1",
    "TLSv1_2"
  ],
  "x509ChainDepth": 2,
  "verifyCertResult": true,
  "verifyHostResult": true,
  "ocspStapled": true,
  "verifyOcspResult": true,
  "certificateChain": [
  {
    "version": 3,
    "subject": "CN=*.search.yahoo.com; O=Yahoo! Inc.; L=Sunnyvale; ST=CA; C=US",
    "issuer": "CN=DigiCert SHA2 High Assurance Server CA; OU=www.digicert.com; O=DigiCert Inc; C=US",
    "subjectCN": "*.search.yahoo.com",
    "subjectAltName": "DNS:*.search.yahoo.com, DNS:search.yahoo.com, DNS:search.yahoo.net, ...",
    "signatureAlg": "sha256WithRSAEncryption",
    "notBefore": "Dec  9 00:00:00 2016 GMT",
    "notAfter": "Apr 30 12:00:00 2017 GMT",
    "expired": false,
    "serialNo": "0F:45:73:E3:F5:7A:7D:5B:43:57:64:2A:6C:46:F2:1C",
    "keyUsage": "Digital Signature, Key Encipherment critical",
    "extKeyUsage": "TLS Web Server Authentication, TLS Web Client Authentication",
    "publicKeyAlg": "RSA",
    "publicKeySize": 2048,
    "basicConstraints": "CA:FALSE critical",
    "subjectKeyIdentifier": "63:0F:82:DB:F9:B0:64:78:90:C9:16:69:95:84:24:F1:4B:04:6F:E4",
    "sha1Fingerprint": "F7:35:E5:C9:A3:60:62:07:CB:55:74:7E:0F:09:AD:2A:F3:F3:53:F3"
  },  {
    "version": 3,
    "subject": "CN=DigiCert SHA2 High Assurance Server CA; OU=www.digicert.com; O=DigiCert Inc; C=US",
    "issuer": "CN=DigiCert High Assurance EV Root CA; OU=www.digicert.com; O=DigiCert Inc; C=US",
    "subjectCN": "DigiCert SHA2 High Assurance Server CA",
    "signatureAlg": "sha256WithRSAEncryption",
    "notBefore": "Oct 22 12:00:00 2013 GMT",
    "notAfter": "Oct 22 12:00:00 2028 GMT",
    "expired": false,
    "serialNo": "04:E1:E7:A4:DC:5C:F2:F3:6D:C0:2B:42:B8:5D:15:9F",
    "keyUsage": "Digital Signature, Certificate Sign, CRL Sign critical",
    "extKeyUsage": "TLS Web Server Authentication, TLS Web Client Authentication",
    "publicKeyAlg": "RSA",
    "publicKeySize": 2048,
    "basicConstraints": "CA:TRUE, pathlen:0 critical",
    "subjectKeyIdentifier": "51:68:FF:90:AF:02:07:75:3C:CC:D9:65:64:62:A2:12:B8:59:72:3B",
    "sha1Fingerprint": "A0:31:C4:67:82:E6:E6:C6:62:C2:C8:7C:76:DA:9A:A6:2C:CA:BD:8E"
  } ]
}
Useful Tip: Use --concurrency=<n> option if you want to scan multiple target servers in parallel.

Usage

The scan output can be shoved into tools like Splunk or ELK for analysis.

Command-line Query & Filter

By passing tls-scan output to JSON command-line parser like jq, you can do realtime filtering on the scan results.

Examples:

Command to filter out hosts that passed certificate and host name verifications:

cat input.txt | tls-scan --port=443  2>/dev/null | \
jq-linux64 -r 'select(.verifyHostResult == true and .verifyCertResult == true) | [.host, .ip, .verifyHost, .verifyCert] | @tsv'

Command to find hosts with expired certificates :

cat input.txt | tls-scan --port=443 --concurrency=500 --timeout=5 2>/dev/null | \
jq-linux64 -r  'select(.certificateChain[].expired == true) | [.host, .ip] | @tsv'

Command to find weak RSA keys :

cat tlscerts.out | \
jq-linux64 -r  'select(.certificateChain[0].publicKeyAlg == "RSA" and .certificateChain[0].publicKeySize < 2048) | [.host, .ip]'

Command to find hosts that support SSLv2 or SSLv3 :

tls-scan --infile=domains.txt --port=443 --version-enum --concurrency=250 --timeout=3 2>/dev/null | \
jq-linux64 -r 'if (.tlsVersions[] | contains("SSL")) == true then [.host, .ip, .tlsVersions[]] else empty end | @tsv'

NOTE: Avoid frequent scan + filter; instead save the scan output to a file and use it to run queries.

Help

Option Description
-H --help Print a usage message briefly summarizing these command-line options and the bug-reporting address, then exit.
-c --connect=<arg> target[:port] to scan. target = {hostname, IPv4, [IPv6] }. IPv6 example: [::1]:443 (default port 443).
--starttls=<protocol> Supported protocols: smtp, imap, pop3, ftp, sieve, nntp, xmpp, ldap, rdp, postgres, mysql, tls (default)
-c --cacert=<file> Root CA file for certificate validation. By default the program attempts to load ca-bundle.crt file from current directory.
-C --ciphers=<arg> Ciphers to use; try openssl ciphers to see all ciphers. Note that this option will be overwritten by --ssl2, --ssl3, --tls1, --tls1_1, --tls1_2 options, if provided. Example: "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384"
-e --cipher-enum Enumerate supported ciphers. Currently use --tls-old ciphers. Try --meta-info to find predefined cipher suite options.
--show-unsupported-ciphers Include unsupported ciphers in the cipher list to JSON output.
-V --version-enum Enumerate supported TLS versions.
-v --version Print tls-scan version and build information.
-r --session-reuse Enable ssl session reuse.
-u --session-print Print SSL session in PEM format to stderr. This is currently not included in the JSON output, but print seperately. This flag woould be useful if you wanted to pass SSL session to --session-file to test session reuse.
-T --session-file=<file> File that contains SSL session in PEM format.
-a --all Shortcut for --version-enum, --cipher-enum and --session-reuse options. This scan can take longer time to complete. Also note if the server employs some form of rate-limiting, your scan may fail.
-s --sni=<host> Set TLS extension servername in ClientHello. Defaults to input hostname and applied to TLSv1+ only.
-b --concurrency=<number> Number of concurrent requests. The default is 1. This option specify the number of worker objects. Concurrency should be set based on your system capacity (memory, cpu, network) etc. Default: 1.
-t --timeout=<number> Timeout per connection (in seconds). Note that is is per connection and for cipher scans, tls-scan makes several connections to the same server. Default: 10.
-S --sleep=<number> Add milliseconds delay between the connection. Only for --cipher-enum and --version-enum options. Useful to manage server rate-limits. The max sleep value is 60000 (1 minute). Default: 0.
-f --infile=<file> Input file with domains or IPs. This is optional and by default the program accepts input from standard input (stdin).
-o --outfile=<file> Output file where the result in JSON format is stored. The default is standard output (stdout).
-n --pretty Pretty print; add newline (\n) between record fields.
-N --nameserver=<ip> DNS resolver IPs to use and is an optional field. Multiple Namespace IP address can be passed. Format: -N <ip1> -N <ip2> -N <ip3>.. In practice, DNS servers may have tight rate-limit in place.
--ssl2 Use only SSLv2 ciphers.
--ssl3 Use only SSLv3 ciphers.
--tls1 Use only TLSv1 ciphers.
--tls1_1 Use only TLSv1_1 ciphers.
--tls1_2 Use only TLSv1_2 ciphers.
--tls-modern Mozilla's modern cipher list. See: https://wiki.mozilla.org/Security/Server_Side_TLS.
--tls-interm Mozilla's intermediate cipher list.
--tls-old Mozilla's old (backward compatible cipher list).
--no-parallel-enum Disable parallel cipher and tls version enumeration. Parallel scan is performed only with '--connect' option.
--meta-info Print program meta information and exit. Useful if you wanted to see predefined cipher options.
--stats-outfile=<file> Enable run-time scan stats and save it to a file

Caveats

  • The following ciphers are currently disabled: SRP:PSK

TLS 1.3 Support

To support old, insecure cipher scans, we are using an old openssl version that doesn't have support for TLS 1.3. So to support TLS 1.3, we need a newer openssl version (v1.1.1+). Since linking two openssl libraries to the same process space doesn't work out of box (duplicate symbols), we chose to use GnuTLS library for TLS 1.3+ support. In short, openssl is used for scanning SSLv2, SSLv3, TLSv1, TLSv1.1 and TLSv1.2 and GnuTLS is used for TLSv1.3.

Contributions

Collaborators and pull requests are welcome!

tls-scan's People

Contributors

joswr1ght avatar mike386 avatar netflash avatar openprunus avatar prbinu avatar semgrep-bot avatar tls-scan avatar vaygr avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tls-scan's Issues

builds fails on Mac OS

running ./build-x86-64.sh on macOS Sierra 10.12.3 gives an error:

  inflating: openssl-1.0.2-chacha/util/x86asm.sh
Configuring for darwin64-x86_64-cc
    no-gmp          [default]  OPENSSL_NO_GMP (skip dir)
    no-krb5         [krb5-flavor not specified] OPENSSL_NO_KRB5
    no-libunbound   [experimental] OPENSSL_NO_LIBUNBOUND (skip dir)
    no-sctp         [default]  OPENSSL_NO_SCTP (skip dir)
    no-shared       [default]
    no-store        [experimental] OPENSSL_NO_STORE (skip dir)
    no-unit-test    [default]  OPENSSL_NO_UNIT_TEST (skip dir)
    no-zlib-dynamic [default]
IsMK1MF=0
CC            =cc
CFLAG         =-DZLIB -DOPENSSL_THREADS -D_REENTRANT -DDSO_DLFCN -DHAVE_DLFCN_H -arch x86_64 -O3 -DL_ENDIAN -Wall -DOPENSSL_EXPERIMENTAL_JPAKE -DOPENSSL_IA32_SSE2 -DOPENSSL_BN_ASM_MONT -DOPENSSL_BN_ASM_MONT5 -DOPENSSL_BN_ASM_GF2m -DSHA1_ASM -DSHA256_ASM -DSHA512_ASM -DMD5_ASM -DAES_ASM -DVPAES_ASM -DBSAES_ASM -DWHIRLPOOL_ASM -DGHASH_ASM -DECP_NISTZ256_ASM
EX_LIBS       = -lz
CPUID_OBJ     =x86_64cpuid.o
BN_ASM        =x86_64-gcc.o x86_64-mont.o x86_64-mont5.o x86_64-gf2m.o rsaz_exp.o rsaz-x86_64.o rsaz-avx2.o
EC_ASM        =ecp_nistz256.o ecp_nistz256-x86_64.o
DES_ENC       =des_enc.o fcrypt_b.o
AES_ENC       =aes-x86_64.o vpaes-x86_64.o bsaes-x86_64.o aesni-x86_64.o aesni-sha1-x86_64.o aesni-sha256-x86_64.o aesni-mb-x86_64.o
BF_ENC        =bf_enc.o
CAST_ENC      =c_enc.o
RC4_ENC       =rc4_enc.o rc4_skey.o
CHACHA_ENC    =chacha_vec.o
POLY1305      =poly1305_vec.o
RC5_ENC       =rc5_enc.o
MD5_OBJ_ASM   =md5-x86_64.o
SHA1_OBJ_ASM  =sha1-x86_64.o sha256-x86_64.o sha512-x86_64.o sha1-mb-x86_64.o sha256-mb-x86_64.o
RMD160_OBJ_ASM=
CMLL_ENC      =cmll-x86_64.o cmll_misc.o
MODES_OBJ     =ghash-x86_64.o aesni-gcm-x86_64.o
ENGINES_OBJ   =
PROCESSOR     =
RANLIB        =/usr/bin/ranlib
ARFLAGS       =
PERL          =/usr/bin/perl
SIXTY_FOUR_BIT_LONG mode
DES_UNROLL used
DES_INT used
RC4_CHUNK is unsigned long
created directory `include'
created directory `include/openssl'
e_os2.h => include/openssl/e_os2.h
/bin/sh: line 0: cd: crypto: No such file or directory
make: *** [links] Error 1
/bin/sh: line 0: cd: crypto: No such file or directory
make: *** [build_crypto] Error 1

Issue in TLS 1.3 custom ciphersuites order

I noticed that in TLS 1.3, tls-scan has issue in the ciphersuites order. It is not sent in the same order as I make it in the command. The ciphersuites order matters in TLS and I need the ciphersuites to be sent on the wire in the same order I make in the command. I hope there is a fix for the issue.

The command
./tls-scan --infile=input.csv --port=443 --cacert=../../../../../etc/ssl/certs/ca-certificates.crt --ciphers="TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256" --outfile=output.json

The issue:
What is actually sent in the client hello (using packet analyser) is the following order:

TLS_AES_256_GCM_SHA384
TLS_CHACHA20_POLY1305_SHA256
TLS_AES_128_GCM_SHA256

The swapped ciphersuites positions are not fixed. In another example, I tried another longer list and the first ciphersuites was in the right position, but it just swapped the second and third. This behaviour is newly introduced with the TLS 1.3 supporting version. The old one was sent in the right order.

--infile Domains w/ Port Numbers

When passing a list of domains with port numbers via --infile, name resolution errors are thrown. It appears to only support the domain, whereas I have them in the file as I would include them individually on the CLI.

For example:

domain.com:443
domain2.com:4443
domain3.com:8080

This is probably more of a feature request than an issue. Can this functionality be added?

Great product, BTW. Really helping with tracking all these certs and capabilities.

Thank you!

Malformed JSON output leads to jq parsing error: "Expected another key-value pair at line X"

tls-scan outputs a malformed JSON line item, which throws errors when trying to parse the output file with jq.

jq error:

parse error: Expected another key-value pair at line 14607, column 43

Line 14607 in tls-scan output file -- notice ending with , char and missing certificateChain key.

{ "host": "XXX", "ip": "XXX", "port": 443, "elapsedTime": 611, "tlsVersion": "TLSv1.2", "cipher": "ADH-AES256-SHA          SSLv3 Kx=DH       Au=None Enc=AES(256)  Mac=SHA1", "tempPublicKeyAlg": "DH", "tempPublicKeySize": 2048, "secureRenego": true, "compression": "NONE", "expansion": "NONE", "sessionLifetimeHint": 300, "x509ChainDepth": -1, "verifyCertResult": true, "verifyHostResult": false, "ocspStapled": false, }

Scan Behavior

I ran a full test (all cipher/protocols) against some of my company's domains, and they said it brought down one of their repo servers. Apparently it made enough calls to kill the service.

Question - does tls-scan iterate through all the cipher suites to enumerate the supported ones? If so, is there another way that such data could be retrieved?

I find it hard to believe it is that hard on the target. I haven't done a packet capture or examined http/s logs yet, just wanted to get a high level understanding first.

Thanks!

Docker build fails

Just tried to build with Docker and it failed with this error message:

...
   creating: openssl-1.0.2-chacha/util/pl/
  inflating: openssl-1.0.2-chacha/util/pl/BC-32.pl  
  inflating: openssl-1.0.2-chacha/util/pl/Mingw32.pl  
  inflating: openssl-1.0.2-chacha/util/pl/OS2-EMX.pl  
  inflating: openssl-1.0.2-chacha/util/pl/VC-32.pl  
  inflating: openssl-1.0.2-chacha/util/pl/linux.pl  
  inflating: openssl-1.0.2-chacha/util/pl/netware.pl  
  inflating: openssl-1.0.2-chacha/util/pl/ultrix.pl  
  inflating: openssl-1.0.2-chacha/util/pl/unix.pl  
  inflating: openssl-1.0.2-chacha/util/pod2man.pl  
  inflating: openssl-1.0.2-chacha/util/pod2mantest  
  inflating: openssl-1.0.2-chacha/util/pod2mantest.pod  
  inflating: openssl-1.0.2-chacha/util/point.sh  
  inflating: openssl-1.0.2-chacha/util/selftest.pl  
  inflating: openssl-1.0.2-chacha/util/shlib_wrap.sh  
  inflating: openssl-1.0.2-chacha/util/sp-diff.pl  
  inflating: openssl-1.0.2-chacha/util/speed.sh  
  inflating: openssl-1.0.2-chacha/util/src-dep.pl  
  inflating: openssl-1.0.2-chacha/util/ssleay.num  
  inflating: openssl-1.0.2-chacha/util/su-filter.pl  
  inflating: openssl-1.0.2-chacha/util/tab_num.pl  
  inflating: openssl-1.0.2-chacha/util/toutf8.sh  
  inflating: openssl-1.0.2-chacha/util/x86asm.sh  
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   315  100   315    0     0    486      0 --:--:-- --:--:-- --:--:--   486

gzip: stdin: not in gzip format
tar: Child returned status 1
tar: Error is not recoverable: exiting now
./build-x86-64.sh: line 7: ./configure: No such file or directory
make: *** No targets specified and no makefile found.  Stop.
make: *** No rule to make target 'install'.  Stop.
>>> Complete
Removing intermediate container 48054589994b
 ---> c01d55f5c7e1
Step 5/12 : FROM ubuntu:16.04
 ---> b6f507652425
Step 6/12 : RUN useradd -rU tls-scan
 ---> Running in 4bc2de3e1f4a
Removing intermediate container 4bc2de3e1f4a
 ---> 4b67cf8dbb37
Step 7/12 : USER tls-scan
 ---> Running in 5cd00d1144a3
Removing intermediate container 5cd00d1144a3
 ---> a65ad0db775a
Step 8/12 : WORKDIR /usr/local/share/tls-scan/
 ---> Running in 9616b8a1ce02
Removing intermediate container 9616b8a1ce02
 ---> 3999fb8962d1
Step 9/12 : COPY --from=builder /usr/local/src/tls-scan/build-root/bin/tls-scan /usr/local/bin/tls-scan
COPY failed: stat usr/local/src/tls-scan/build-root/bin/tls-scan: file does not exist

I've simply cloned the repository and ran the Docker command as shown in description docker build -t tls-scan .

Feature Requets: Error Logging

Hi, is it possible to add a feature for logging errors when the TLS handshake fails and can not obtain results? Mainly that specifies the domain name or IP address of the requested address, the error message, date/time and save them in a file? Can this be an argument in the command (so we enable it when needed).

zlib-1.2.13 not available

Following docker build instructions and the build failed due to http://zlib.net/zlib-1.2.13.tar.gz returning 404.
Making the below zlib version change to 1.3 allowed the build to complete, and seems functional.

diff --git a/bootstrap.sh b/bootstrap.sh
index 1cb8210..5029be6 100755
--- a/bootstrap.sh
+++ b/bootstrap.sh
@@ -45,7 +45,7 @@ export PKG_CONFIG_PATH=${OUTDIR}/lib/pkgconfig

 OPENSSL_VERSION="1.0.2-chacha"
 LIBEVENT_VERSION="2.1.8-stable"
-ZLIB_VERSION="zlib-1.2.13"
+ZLIB_VERSION="zlib-1.3"

Query about acknowledgement

Hi, sorry for posting this in the issues but I do not have any other method of communication. We would like to acknowledge you in a work that used tls-scan as follows:

"We thank [...] and the "tls-scan" developer, Binu Ramakrishnan, for technical support.".

Is this your name you would like us to use in an acknowledgement?

What are the default ciphers offered by tls-scan?

Hi. If I did not specify the ciphers using -C --ciphers=<arg>
nor specified a version's ciphers using --tls1_1 what are the ciphers that the tls-scan will offer to the server? It is important to know as these will affect the server's response. For example, if there is a cipher a tls-scan did not offer from the 1st place, the server will never choose it. So it is important for me to knwo in order to draw the conclusions.
Also, can you give a brief idea of the methodology used? does tls-scan examine one cipher at time? I will use tls-scan for a research and it is useful to know what's your methodology please.

Feature request: Support client certificate

Do you think we could use pls-scan to test some servers that require client authentication.

Would it be possible to parse the accepted CA list. You can get that information using the -prexit option serverfault question
Also, it would be good to have a way to pass the client certificate as an option to tls-scan.

If you point me to the relevant part of the code, I could try to help implementing that.

IPv6 address in `--connect` do not work and IP get's malformed

# ❯ ./tls-scan --ip --sni='cert.chief.app' --connect='2a0b:3c40:15:0:185:208:210:201:443' --cacert='cacert.pem'
parsing: ip: 2a0b:3c40:15:0:185:208:210:201:443; 
parsing: ip: 2a0b:3c40:15:0:185:208:210:201; 
trying: ip: 2a0b:3c40:15:0:185:208:210; port:201 
host: ; ip: 2a0b:3c40:15:0:185:208:210; error: Failed to connect remote ip
 pid: 29326 | ciphers: (0) |dns-lookup: 1 |network-error: 0 |dns-errcount: 0 |remote-close-error: 0 |unknown-error: 0 |connect-error: 1 |timeout-error: 0 |tls-handshake: 0 |gross-tls-handshake: 0 |elapsed-time: 0.14575 secs

It looks like when specifying an IPv6 address using the --connect option the IP get's parsed twice striping the last part of an IPv6 address to be used as port which breaks the connection for obvious reasons 😄

As you can see I have been trying to debug this to see if I can find a solution but my C is not very good unfortunately and I was unable to figure out a solution...

I also tried using [ipv6]:port but that made it even worse and looking at the code that is not a format that can be handled.

Hope this is an easy for for someone that knows what they are doing.

Docker build fails:

gcc -I./include -I /usr/local/include -Wall -Wundef -Wshadow -Wunreachable-code -Wswitch-default -Wcast-align -pedantic -g -std=c99 -Wl,-rpath,/usr/local/lib -D_GNU_SOURCE   -c -o main.o main.c
main.c: In function 'main':
main.c:1130:5: error: 'options_t {aka struct options}' has no member named 'ssl3'
   op.ssl3 = false;
     ^
main.c:1131:5: error: 'options_t {aka struct options}' has no member named 'tls1'
   op.tls1 = false;
     ^
main.c:1132:5: error: 'options_t {aka struct options}' has no member named 'tls1_1'
   op.tls1_1 = false;
     ^
main.c:1133:5: error: 'options_t {aka struct options}' has no member named 'tls1_2'
   op.tls1_2 = false;
     ^
main.c:1243:9: error: 'options_t {aka struct options}' has no member named 'ssl3'
       op.ssl3 = true;
         ^
main.c:1247:9: error: 'options_t {aka struct options}' has no member named 'tls1'
       op.tls1 = true;
         ^
main.c:1251:9: error: 'options_t {aka struct options}' has no member named 'tls1_1'
       op.tls1_1 = true;
         ^
main.c:1255:9: error: 'options_t {aka struct options}' has no member named 'tls1_2'
       op.tls1_2 = false;
         ^
main.c:1435:21: warning: format '%llu' expects argument of type 'long long unsigned int', but argument 4 has type 'uint64_t {aka long unsigned int}' [-Wformat=]
     fprintf(stderr, " [%d] elapsed-time        : %llu.%llu secs\n",
                     ^
main.c:1435:21: warning: format '%llu' expects argument of type 'long long unsigned int', but argument 5 has type 'uint64_t {aka long unsigned int}' [-Wformat=]
main.c:1461:21: warning: format '%llu' expects argument of type 'long long unsigned int', but argument 3 has type 'uint64_t {aka long unsigned int}' [-Wformat=]
     fprintf(stderr, "elapsed-time: %llu.%llu secs\n", et/1000000, et%1000000);
                     ^
main.c:1461:21: warning: format '%llu' expects argument of type 'long long unsigned int', but argument 4 has type 'uint64_t {aka long unsigned int}' [-Wformat=]
<builtin>: recipe for target 'main.o' failed
make: *** [main.o] Error 1
The command '/bin/sh -c ./build-x86-64.sh' returned a non-zero code: 2

Incorrect `issuer` value

While using prebuild tls-scan in version 1.5.0, it seems that the value of the issuer is being set incorrectly to the same value as subject.

The result of tls-scan --connect twitter.com --cacert /etc/ssl/certs/ca-certificates.crt --pretty is:

{
  "host": "twitter.com",
  "ip": "104.244.42.193",
  "port": 443,
  "elapsedTime": 38,
  "tlsVersion": "TLSv1.2",
  "cipher": "ECDHE-ECDSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH     Au=ECDSA Enc=AESGCM(128) Mac=AEAD",
  "tempPublicKeyAlg": "ECDH prime256v1",
  "tempPublicKeySize": 256,
  "secureRenego": true,
  "compression": "NONE",
  "expansion": "NONE",
  "sessionLifetimeHint": 7200,
  "x509ChainDepth": 2,
  "verifyCertResult": true,
  "verifyHostResult": true,
  "ocspStapled": false,
  "certificateChain": [
  {
    "version": 3,
    "subject": "CN=twitter.com; O=Twitter, Inc.; L=San Francisco; ST=California; C=US",
    "issuer": "CN=twitter.com; O=Twitter, Inc.; L=San Francisco; ST=California; C=US",
    "subjectCN": "twitter.com",
    "subjectAltName": "DNS:twitter.com, DNS:www.twitter.com",
    "signatureAlg": "ecdsa-with-SHA384",
    "notBefore": "Feb  5 00:00:00 2023 GMT",
    "notAfter": "Feb  5 23:59:59 2024 GMT",
    "expired": false,
    "serialNo": "04:53:47:D1:33:42:4A:B1:A3:4F:B3:CD:4D:6A:3C:DC",
    "keyUsage": "Digital Signature critical",
    "extKeyUsage": "TLS Web Server Authentication, TLS Web Client Authentication",
    "publicKeyAlg": "ECC prime256v1",
    "publicKeySize": 256,
    "basicConstraints": "CA:FALSE",
    "subjectKeyIdentifier": "91:67:46:DA:C0:8B:B0:73:42:B3:E5:B7:6A:80:D1:08:B6:C3:20:5B",
    "sha1Fingerprint": "C3:9A:EA:C1:5F:4F:8C:FF:C4:40:36:00:F8:61:42:C2:65:11:95:D3"
  },  {
    "version": 3,
    "subject": "CN=DigiCert TLS Hybrid ECC SHA384 2020 CA1; O=DigiCert Inc; C=US",
    "issuer": "CN=DigiCert TLS Hybrid ECC SHA384 2020 CA1; O=DigiCert Inc; C=US",
    "subjectCN": "DigiCert TLS Hybrid ECC SHA384 2020 CA1",
    "signatureAlg": "sha384WithRSAEncryption",
    "notBefore": "Apr 14 00:00:00 2021 GMT",
    "notAfter": "Apr 13 23:59:59 2031 GMT",
    "expired": false,
    "serialNo": "07:F2:F3:5C:87:A8:77:AF:7A:EF:E9:47:99:35:25:BD",
    "keyUsage": "Digital Signature, Certificate Sign, CRL Sign critical",
    "extKeyUsage": "TLS Web Server Authentication, TLS Web Client Authentication",
    "publicKeyAlg": "ECC secp384r1",
    "publicKeySize": 384,
    "basicConstraints": "CA:TRUE, pathlen:0 critical",
    "subjectKeyIdentifier": "0A:BC:08:29:17:8C:A5:39:6D:7A:0E:CE:33:C7:2E:B3:ED:FB:C3:7A",
    "sha1Fingerprint": "AE:C1:3C:DD:5E:A6:A3:99:8A:EC:14:AC:33:1A:D9:6B:ED:BB:77:0F"
  } ]
}

As you can see, the result claims that the issuer of the Twitter certificate is CN=twitter.com; O=Twitter, Inc.; L=San Francisco; ST=California; C=US which is wrong.

It seems that the problematic part is here:

tls-scan/cert-parser.c

Lines 862 to 872 in c9d9af4

if (tls_cert->x509[i].issuer) {
BIO_get_mem_ptr(tls_cert->x509[i].issuer, &bptr);
if (!tls_cert->verify_cert) {
oblen = ts_json_escape(bptr->data, bptr->length, &outbuffer[0],
outbuffer_length);
}
fprintf(fp, "%.*s\"issuer\": \"%.*s\",%c", FMT_INDENT(4),
(int)oblen, outbuffer, fmt);
}
:

LibreSSL support

It'd be great to be able to build tls-scan with LibreSSL as it'll improve portability by a lot.

There are several things here:

  1. There's no ASN1_TIME_diff() in LibreSSL. Some simply backport that function for compatibility.
  2. For COMP_METHOD support it needs to have an additional <openssl/comp.h> include, but there's no SSL_COMP_free_compression_methods() though.
  3. SSL_get_server_tmp_key() and X509_check_host() didn't exist in older versions, but as of 2.5.5 they're there.
  4. SSLv2_client_method() was dropped long time ago as an insecure and is not present in any version whatsoever.

The most of these can be resolved by ifdef's I think.

Malformed json output for some domains

Some domains return an invalid json output. Look for example at the response below from tls-scan --cacert /etc/ssl/certs/ca-certificates.crt --all -c wolfgangmobile.com. It seems to go wrong at the tlsVersions key, where an array is opened but never closed.

{ "host": "wolfgangmobile.com", "ip": "34.249.138.199", "port": 443, "elapsedTime": 4922, "tlsVersion": "TLSv1.2", "cipher": "ECDHE-RSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH     Au=RSA  Enc=AESGCM(128) Mac=AEAD", "tempPublicKeyAlg": "ECDH prime256v1", "tempPublicKeySize": 256, "secureRenego": true, "compression": "NONE", "expansion": "NONE", "sessionLifetimeHint": 7200, "tlsVersions": [ "cipherSuite": { "supported": [ "ECDHE-RSA-AES256-GCM-SHA384", "ECDHE-RSA-AES256-SHA384", "ECDHE-RSA-AES256-SHA", "AES256-GCM-SHA384", "AES256-SHA256", "AES256-SHA", "ECDHE-RSA-AES128-GCM-SHA256", "ECDHE-RSA-AES128-SHA256", "ECDHE-RSA-AES128-SHA", "AES128-GCM-SHA256", "AES128-SHA256", "AES128-SHA" ] }, "x509ChainDepth": 3, "verifyCertResult": false, "verifyCertError": "certificate has expired", "verifyHostResult": true, "ocspStapled": false, "ocspStapled": false, "certificateChain": [ { "version": 3, "subject": "CN=wolfgangmobile.com", "issuer": "CN=R3; O=Let's Encrypt; C=US", "subjectCN": "wolfgangmobile.com", "subjectAltName": "DNS:*.wolfgangmobile.com, DNS:wolfgangmobile.com", "signatureAlg": "sha256WithRSAEncryption", "notBefore": "Dec 11 00:09:26 2021 GMT", "notAfter": "Mar 11 00:09:25 2022 GMT", "expired": false, "serialNo": "03:65:44:7C:58:15:BE:86:A2:29:90:8A:7D:01:A3:E9:B7:69", "keyUsage": "Digital Signature, Key Encipherment critical", "extKeyUsage": "TLS Web Server Authentication, TLS Web Client Authentication", "publicKeyAlg": "RSA", "publicKeySize": 2048, "basicConstraints": "CA:FALSE critical", "subjectKeyIdentifier": "91:70:F6:7B:F3:46:95:40:49:28:6F:A2:B8:CB:5D:C5:21:9C:F0:48", "sha1Fingerprint": "36:DA:9E:9D:41:CB:0B:6F:D4:00:3F:F3:CF:71:2D:6A:59:55:BC:EB" },{ "version": 3, "subject": "CN=R3; O=Let's Encrypt; C=US", "issuer": "CN=ISRG Root X1; O=Internet Security Research Group; C=US", "subjectCN": "R3", "signatureAlg": "sha256WithRSAEncryption", "notBefore": "Sep  4 00:00:00 2020 GMT", "notAfter": "Sep 15 16:00:00 2025 GMT", "expired": false, "serialNo": "91:2B:08:4A:CF:0C:18:A7:53:F6:D6:2E:25:A7:5F:5A", "keyUsage": "Digital Signature, Certificate Sign, CRL Sign critical", "extKeyUsage": "TLS Web Client Authentication, TLS Web Server Authentication", "publicKeyAlg": "RSA", "publicKeySize": 2048, "basicConstraints": "CA:TRUE, pathlen:0 critical", "subjectKeyIdentifier": "14:2E:B3:17:B7:58:56:CB:AE:50:09:40:E6:1F:AF:9D:8B:14:C2:C6", "sha1Fingerprint": "A0:53:37:5B:FE:84:E8:B7:48:78:2C:7C:EE:15:82:7A:6A:F5:A4:05" },{ "version": 3, "subject": "CN=ISRG Root X1; O=Internet Security Research Group; C=US", "issuer": "CN=DST Root CA X3; O=Digital Signature Trust Co.", "subjectCN": "ISRG Root X1", "signatureAlg": "sha256WithRSAEncryption", "notBefore": "Jan 20 19:14:03 2021 GMT", "notAfter": "Sep 30 18:14:03 2024 GMT", "expired": false, "serialNo": "40:01:77:21:37:D4:E9:42:B8:EE:76:AA:3C:64:0A:B7", "keyUsage": "Certificate Sign, CRL Sign critical", "publicKeyAlg": "RSA", "publicKeySize": 4096, "basicConstraints": "CA:TRUE critical", "subjectKeyIdentifier": "79:B4:59:E6:7B:B6:E5:E4:01:73:80:08:88:C8:1A:58:F6:E9:9B:6E", "sha1Fingerprint": "93:3C:6D:DE:E9:5C:9C:41:A4:0F:9F:50:49:3D:82:BE:03:AD:87:BF" } ] }

Unable to Connect Using >TLS1.1 Protocol w/ Apache

I setup a new Apache server with the following SSLProtocol setting:

SSLProtocol -all TLSv1.2 TLSv1.3

tls-scan returns a network error when attempting to connect. elinks returns an "unable to retrieve" SSL error.

When I revert to the following, both applications connect as expected:

SSLProtocol all

My assumption here is cipher suite support - specifically, tls-scan and elinks might not like ECDHE. Have you had any other reports of this problem? Does my analysis sound sane or is there another issue that I'm completely missing?

As always, thanks for your support and for making a great tool!

Randal

--cipher argument does not accept chacha or RSA ciphers.

Hi, when I try to specify the ciphers as follows (I also tried to enter the ciphersuites with/without quotations):
--ciphers=ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-SHA

When I check the client hello in wireshark, I see only one actual cipher which is:
Cipher Suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA (0xc00a)

Can you please clarify to me how can I specify the ciphers correctly? in particular chacha ciphers?

JSON output from scan is non-compliant

i've been using tls-scan to perform an audit of certificates on my local network. the output from the scan is meant to be in JSON format, but it appears to be non-compliant.

if i use https://jsonlint.com/ or https://jsonformatter.org/ i get parsing errors.
same problem if i try to use JSON import into Excel.

if there is another product or something i can use to view or convert the results i'm happy to use this.
otherwise the output may need to be changed.

at this stage, i'd even be happy for a rex/sed/shell hack of any kind to convert the output.

does anyone have any ideas?

my goal is simply to be able to get the scanned data into a nice readable format of some kind.
i need to be able to see the IP address, the port number, the certificate which was found and
the related certificate dates. the other data would be nice as well, but not essential.

many thanks in advance.

Docker build error: no such file or directory

Steps to reproduce:

git clone [email protected]:prbinu/tls-scan.git
cd tls-scan
docker build -t tls-scan .

I received the following output:

[+] Building 47.7s (12/13)
 => [internal] load build definition from Dockerfile                         0.0s
 => => transferring dockerfile: 680B                                         0.0s
 => [internal] load .dockerignore                                            0.0s
 => => transferring context: 2B                                              0.0s
 => [internal] load metadata for docker.io/library/ubuntu:18.04              2.7s
 => https://curl.haxx.se/ca/cacert.pem                                       0.0s
 => [internal] load build context                                            2.0s
 => => transferring context: 870.76kB                                        1.7s
 => [builder 1/4] FROM docker.io/library/ubuntu:18.04@sha256:daf3e62183e8aa  3.3s
 => => resolve docker.io/library/ubuntu:18.04@sha256:daf3e62183e8aa9a56878a  0.0s
 => => sha256:daf3e62183e8aa9a56878a685ed26f3af3dd8c08c8fd1 1.41kB / 1.41kB  0.0s
 => => sha256:9ad19d39c58f78bb262e777201ff498b2be5b1f020ac36972 529B / 529B  0.0s
 => => sha256:251b86c83674d45abbf5736ae35654fca6145e9aaaf14 1.46kB / 1.46kB  0.0s
 => => sha256:fb668870d8a72b5d72a3b6d98ee626e00f9f7c29c6f 26.71MB / 26.71MB  2.5s
 => => extracting sha256:fb668870d8a72b5d72a3b6d98ee626e00f9f7c29c6f4f7d3a6  0.7s
 => [stage-1 2/5] RUN useradd -rU tls-scan                                   0.4s
 => [builder 2/4] RUN set -xeu;     apt-get update;     apt-get install -y  28.0s
 => [stage-1 3/5] WORKDIR /usr/local/share/tls-scan/                         0.0s
 => [builder 3/4] COPY . /usr/local/src/tls-scan                             0.0s
 => [builder 4/4] RUN set -xeu;     cd /usr/local/src/tls-scan;     ./buil  13.5s
 => ERROR [stage-1 4/5] COPY --from=builder /usr/local/src/tls-scan/build-r  0.0s
------
 > [stage-1 4/5] COPY --from=builder /usr/local/src/tls-scan/build-root/bin/tls-scan /usr/local/bin/tls-scan:
------
failed to compute cache key: failed to walk /var/lib/docker/tmp/buildkit-mount3498967087/usr/local/src/tls-scan/build-root/bin: lstat /var/lib/docker/tmp/buildkit-mount3498967087/usr/local/src/tls-scan/build-root/bin: no such file or directory

Any idea what is happening here?

I am running on OSX, here is some information about my system:

System

$ neofetch
                    'c.          
                 ,xNMM.          --------------------------------------
               .OMMMMo           OS: macOS 12.6.1 21G217 x86_64
               OMMM0,            Host: MacBookPro16,1
     .;loddo:' loolloddol;.      Kernel: 21.6.0
   cKMMMMMMMMMMNWMMMMMMMMMM0:    Uptime: 8 days, 31 mins
 .KMMMMMMMMMMMMMMMMMMMMMMMWd.    Packages: 274 (brew)
 XMMMMMMMMMMMMMMMMMMMMMMMX.      Shell: zsh 5.8.1
;MMMMMMMMMMMMMMMMMMMMMMMM:       Resolution: 2560x1440, 1792x1120, 2560x1440
:MMMMMMMMMMMMMMMMMMMMMMMM:       DE: Aqua
.MMMMMMMMMMMMMMMMMMMMMMMMX.      WM: Spectacle
 kMMMMMMMMMMMMMMMMMMMMMMMMWd.    Terminal: WarpTerminal
 .XMMMMMMMMMMMMMMMMMMMMMMMMMMk   CPU: Intel i9-9880H (16) @ 2.30GHz
  .XMMMMMMMMMMMMMMMMMMMMMMMMK.   GPU: Intel UHD Graphics 630, AMD Radeon Pro 5500
    kMMMMMMMMMMMMMMMMMMMMMMd     Memory: 19305MiB / 32768MiB
     ;KMMMMMMMWXXWMMMMMMMk.
       .cooc,.    .,coo:.

Docker

$ docker --version
Docker version 20.10.21, build baeda1f

Issues in parsing the results

Hi. I have conducted the scan for 1M domains. The results are saved in .json file. I added all the objects in an array and separated the objects by comma. Unfortunately, conventional python parsers could not load the array seemingly due to memory. I tried to install jq-linux64 but Ubuntu can't get it:

sudo apt-get install jq-linux64 
Reading package lists... Done
Building dependency tree       
Reading state information... Done
E: Unable to locate package jq-linux64

Can you please advise me on how to parse the json file with 2.4 GB? I also tried jq but it kept pointing errors in the file and failed.

I probably should have made the filtering during the scan. But I can't find the tool jq-linux64. If I want to filter during the scan using jq can you write a simple example syntax with jq for example to get host, ip, port?

jq can only parse array, with objects separated by comma. How to parse tls-scan output from the command line using jq?

/home/e/Downloads/ts-build-root/build/tls-scan-master/cert-parser.c:514: undefined reference to `SSLv3_client_method' collect2: error: ld returned 1 exit status

I need to compile tls-scan on OpenSSL 1.1.0g with default settings (sslv3 disabled) except that I enable weak-ciphers because I need one DES cipher. Here is my config line that I edited in the 1.1.0 build file here: https://github.com/prbinu/tls-scan/blob/master/build-x86-64-openssl-1.1.0.sh
I just changed the ./config command to:
./config enable-static-engine enable-weak-ssl-ciphers enable-zlib no-shared --prefix=${OUTDIR} --openssldir=${OUTDIR}/ssl -I${OUTDIR}/include -L${OUTDIR}/lib --with-zlib-lib=${OUTDIR}/lib --with-zlib-include=${OUTDIR}/include

When I run this command: sudo ./build-x86-64-openssl-1.1.0.sh I get these errors and warnings, apparently, tls-scan requires SSLv3 methods, but I do not want to enable SSLv3 in my case. All what I need is shown in my configuration command above, weak-ciphers but no weak versions needed. Can you please help me fix the issue?


cert-parser.c:514:12: warning: implicit declaration of function ‘SSLv3_client_method’; did you mean ‘SSLv23_client_method’? [-Wimplicit-function-declaration]
     return SSLv3_client_method();
            ^~~~~~~~~~~~~~~~~~~
            SSLv23_client_method
cert-parser.c:514:12: warning: return makes pointer from integer without a cast [-Wint-conversion]
     return SSLv3_client_method();
            ^~~~~~~~~~~~~~~~~~~~~
cert-parser.c:516:5: warning: ‘TLSv1_client_method’ is deprecated [-Wdeprecated-declarations]
     return TLSv1_client_method();
     ^~~~~~
In file included from /home/e/Downloads/ts-build-root/include/openssl/ct.h:13:0,
                 from /home/e/Downloads/ts-build-root/include/openssl/ssl.h:61,
                 from cert-parser.c:5:
/home/e/Downloads/ts-build-root/include/openssl/ssl.h:1626:45: note: declared here
 DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_client_method(void)) /* TLSv1.0 */
                                             ^
/home/e/Downloads/ts-build-root/include/openssl/opensslconf.h:96:35: note: in definition of macro ‘DECLARE_DEPRECATED’
 # define DECLARE_DEPRECATED(f)    f __attribute__ ((deprecated));
                                   ^
/home/e/Downloads/ts-build-root/include/openssl/ssl.h:1626:1: note: in expansion of macro ‘DEPRECATEDIN_1_1_0’
 DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_client_method(void)) /* TLSv1.0 */
 ^~~~~~~~~~~~~~~~~~
cert-parser.c:518:5: warning: ‘TLSv1_1_client_method’ is deprecated [-Wdeprecated-declarations]
     return TLSv1_1_client_method();
     ^~~~~~
In file included from /home/e/Downloads/ts-build-root/include/openssl/ct.h:13:0,
                 from /home/e/Downloads/ts-build-root/include/openssl/ssl.h:61,
                 from cert-parser.c:5:
/home/e/Downloads/ts-build-root/include/openssl/ssl.h:1632:45: note: declared here
 DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_1_client_method(void)) /* TLSv1.1 */
                                             ^
/home/e/Downloads/ts-build-root/include/openssl/opensslconf.h:96:35: note: in definition of macro ‘DECLARE_DEPRECATED’
 # define DECLARE_DEPRECATED(f)    f __attribute__ ((deprecated));
                                   ^
/home/e/Downloads/ts-build-root/include/openssl/ssl.h:1632:1: note: in expansion of macro ‘DEPRECATEDIN_1_1_0’
 DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_1_client_method(void)) /* TLSv1.1 */
 ^~~~~~~~~~~~~~~~~~
cert-parser.c:520:5: warning: ‘TLSv1_2_client_method’ is deprecated [-Wdeprecated-declarations]
     return TLSv1_2_client_method();
     ^~~~~~
In file included from /home/e/Downloads/ts-build-root/include/openssl/ct.h:13:0,
                 from /home/e/Downloads/ts-build-root/include/openssl/ssl.h:61,
                 from cert-parser.c:5:
/home/e/Downloads/ts-build-root/include/openssl/ssl.h:1638:45: note: declared here
 DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_2_client_method(void)) /* TLSv1.2 */
                                             ^
/home/e/Downloads/ts-build-root/include/openssl/opensslconf.h:96:35: note: in definition of macro ‘DECLARE_DEPRECATED’
 # define DECLARE_DEPRECATED(f)    f __attribute__ ((deprecated));
                                   ^
/home/e/Downloads/ts-build-root/include/openssl/ssl.h:1638:1: note: in expansion of macro ‘DEPRECATEDIN_1_1_0’
 DEPRECATEDIN_1_1_0(__owur const SSL_METHOD *TLSv1_2_client_method(void)) /* TLSv1.2 */
 ^~~~~~~~~~~~~~~~~~
gcc -I./include -I /home/e/Downloads/ts-build-root/include -Wall -Wundef -Wshadow -Wunreachable-code -Wswitch-default -Wcast-align -pedantic -g -std=c99 -Wl,-rpath,/home/e/Downloads/ts-build-root/lib -D_GNU_SOURCE   -c -o common.o common.c
common.c: In function ‘init_stats’:
common.c:15:3: warning: implicit declaration of function ‘gettimeofday’ [-Wimplicit-function-declaration]
   gettimeofday(&st->start_time, NULL);
   ^~~~~~~~~~~~
gcc -I./include -I /home/e/Downloads/ts-build-root/include -Wall -Wundef -Wshadow -Wunreachable-code -Wswitch-default -Wcast-align -pedantic -g -std=c99 -Wl,-rpath,/home/e/Downloads/ts-build-root/lib -D_GNU_SOURCE   -c -o proto-adapters.o proto-adapters.c
proto-adapters.c: In function ‘on_smtp_read’:
proto-adapters.c:203:31: warning: ‘%s’ directive output may be truncated writing up to 255 bytes into a region of size 123 [-Wformat-truncation=]
     snprintf(ehlo, 128, "EHLO %s\r\n", cli->host);
                               ^~
proto-adapters.c:203:5: note: ‘snprintf’ output between 8 and 263 bytes into a destination of size 128
     snprintf(ehlo, 128, "EHLO %s\r\n", cli->host);
     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gcc -I./include -I /home/e/Downloads/ts-build-root/include -Wall -Wundef -Wshadow -Wunreachable-code -Wswitch-default -Wcast-align -pedantic -g -std=c99 -Wl,-rpath,/home/e/Downloads/ts-build-root/lib -D_GNU_SOURCE   -c -o main.o main.c
main.c: In function ‘ts_ssl_destroy’:
main.c:241:3: warning: ‘ERR_remove_thread_state’ is deprecated [-Wdeprecated-declarations]
   ERR_remove_thread_state(NULL);
   ^~~~~~~~~~~~~~~~~~~~~~~
In file included from /home/e/Downloads/ts-build-root/include/openssl/ct.h:13:0,
                 from /home/e/Downloads/ts-build-root/include/openssl/ssl.h:61,
                 from main.c:17:
/home/e/Downloads/ts-build-root/include/openssl/err.h:247:25: note: declared here
 DEPRECATEDIN_1_1_0(void ERR_remove_thread_state(void *))
                         ^
/home/e/Downloads/ts-build-root/include/openssl/opensslconf.h:96:35: note: in definition of macro ‘DECLARE_DEPRECATED’
 # define DECLARE_DEPRECATED(f)    f __attribute__ ((deprecated));
                                   ^
/home/e/Downloads/ts-build-root/include/openssl/err.h:247:1: note: in expansion of macro ‘DEPRECATEDIN_1_1_0’
 DEPRECATEDIN_1_1_0(void ERR_remove_thread_state(void *))
 ^~~~~~~~~~~~~~~~~~
main.c: In function ‘main’:
main.c:1427:53: warning: format ‘%llu’ expects argument of type ‘long long unsigned int’, but argument 4 has type ‘uint64_t {aka long unsigned int}’ [-Wformat=]
     fprintf(stderr, " [%d] elapsed-time        : %llu.%llu secs\n",
                                                  ~~~^
                                                  %lu
                                             getpid(),  et/1000000, et%1000000);
                                                        ~~~~~~~~~~
main.c:1427:58: warning: format ‘%llu’ expects argument of type ‘long long unsigned int’, but argument 5 has type ‘uint64_t {aka long unsigned int}’ [-Wformat=]
     fprintf(stderr, " [%d] elapsed-time        : %llu.%llu secs\n",
                                                       ~~~^
                                                       %lu
                                             getpid(),  et/1000000, et%1000000);
                                                                    ~~~~~~~~~~
main.c:1453:39: warning: format ‘%llu’ expects argument of type ‘long long unsigned int’, but argument 3 has type ‘uint64_t {aka long unsigned int}’ [-Wformat=]
     fprintf(stderr, "elapsed-time: %llu.%llu secs\n", et/1000000, et%1000000);
                                    ~~~^               ~~~~~~~~~~
                                    %lu
main.c:1453:44: warning: format ‘%llu’ expects argument of type ‘long long unsigned int’, but argument 4 has type ‘uint64_t {aka long unsigned int}’ [-Wformat=]
     fprintf(stderr, "elapsed-time: %llu.%llu secs\n", et/1000000, et%1000000);
                                         ~~~^                      ~~~~~~~~~~
                                         %lu
main.c: In function ‘ts_scan_tcp_connect’:
main.c:769:24: warning: ‘%d’ directive writing between 1 and 5 bytes into a region of size between 0 and 255 [-Wformat-overflow=]
   sprintf(ip_port, "%s:%d", cli->ip, cli->port);
                        ^~
main.c:769:3: note: ‘sprintf’ output between 3 and 262 bytes into a destination of size 256
   sprintf(ip_port, "%s:%d", cli->ip, cli->port);
   ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
gcc -o tls-scan cert-parser.o common.o proto-adapters.o main.o -L /home/e/Downloads/ts-build-root/lib -L /home/e/Downloads/ts-build-root/lib -lssl -L /home/e/Downloads/ts-build-root/lib -lcrypto -L /home/e/Downloads/ts-build-root/lib -levent -L /home/e/Downloads/ts-build-root/lib -levent_openssl -ldl -lpthread -L /home/e/Downloads/ts-build-root/lib -lz -lrt
cert-parser.o: In function `ts_tls_get_method':
/home/e/Downloads/ts-build-root/build/tls-scan-master/cert-parser.c:514: undefined reference to `SSLv3_client_method'
collect2: error: ld returned 1 exit status
Makefile:32: recipe for target 'tls-scan' failed
make: *** [tls-scan] Error 1

tls-scan not working

Hi @prbinu :)
While installing tls-scan on droplet form digital ocean . it gives me that ./tls-scan command not found . i make sure that i have installed requirements

checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /usr/bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking whether make supports nested variables... yes
checking for gcc... gcc
checking whether the C compiler works... yes
checking for C compiler default output file name... a.out
checking for suffix of executables...
checking whether we are cross compiling... no
checking for suffix of object files... o
checking whether we are using the GNU C compiler... yes
checking whether gcc accepts -g... yes
checking for gcc option to accept ISO C89... none needed
checking whether gcc understands -c and -o together... yes
checking whether make supports the include directive... yes (GNU style)
checking dependency style of gcc... gcc3
checking build system type... x86_64-pc-linux-gnu
checking host system type... x86_64-pc-linux-gnu
checking that generated files are newer than configure... done
configure: creating ./config.status
config.status: creating Makefile
config.status: executing depfiles commands
gcc -DPACKAGE_NAME="tls-scan" -DPACKAGE_TARNAME="tls-scan" -DPACKAGE_VERSION="1.4.1" -DPACKAGE_STRING="tls-scan\ 1.4.1" -DPACKAGE_BUGREPORT="" -DPACKAGE_URL="" -DPACKAGE="tls-scan" -DVERSION="1.4.1" -I. -I./include -I build-root/include -I build-root/include -Wall -Wundef -Wshadow -Wunreachable-code -Wswitch-default -Wcast-align -pedantic -g -std=c99 -D_GNU_SOURCE -DTS_VERSION="1.4.3" -DTS_BUILD_DATE="2020-06-28" -DTS_OS="Linux" -g -O2 -MT main.o -MD -MP -MF .deps/main.Tpo -c -o main.o main.c
In file included from ./include/proto-adapters.h:8,
from main.c:29:
./include/common.h:18:10: fatal error: gnutls/gnutls.h: No such file or directory
#include <gnutls/gnutls.h>
^~~~~~~~~~~~~~~~~
compilation terminated.
make: *** [Makefile:439: main.o] Error 1
gcc -DPACKAGE_NAME="tls-scan" -DPACKAGE_TARNAME="tls-scan" -DPACKAGE_VERSION="1.4.1" -DPACKAGE_STRING="tls-scan\ 1.4.1" -DPACKAGE_BUGREPORT="" -DPACKAGE_URL="" -DPACKAGE="tls-scan" -DVERSION="1.4.1" -I. -I./include -I build-root/include -I build-root/include -Wall -Wundef -Wshadow -Wunreachable-code -Wswitch-default -Wcast-align -pedantic -g -std=c99 -D_GNU_SOURCE -DTS_VERSION="1.4.3" -DTS_BUILD_DATE="2020-06-28" -DTS_OS="Linux" -g -O2 -MT main.o -MD -MP -MF .deps/main.Tpo -c -o main.o main.c
In file included from ./include/proto-adapters.h:8,
from main.c:29:
./include/common.h:18:10: fatal error: gnutls/gnutls.h: No such file or directory
#include <gnutls/gnutls.h>
^~~~~~~~~~~~~~~~~
compilation terminated.
make: *** [Makefile:439: main.o] Error 1

Complete
root@omar:/aws/tls-scan# cd build-root/
root@omar:
/aws/tls-scan/build-root# cd bin/
root@omar:/aws/tls-scan/build-root/bin# ./tls-scan
-bash: ./tls-scan: No such file or directory
root@omar:
/aws/tls-scan/build-root/bin# ./tls-scan --connect=yahoo.com --cacert=../etc/tls-scan/ca-bundle.crt --pretty
-bash: ./tls-scan: No such file or directory
root@omar:~/aws/tls-scan/build-root/bin# tls-scan
-bash: tls-scan: command not found
======================================
Thanks ,

Install fails when trying to extract zlib-1.3.tar.gz

zlib has been updated to v1.3.1. Similar to issue #59.

Running:
sudo ./bootstrap.h -v

Error:
gzip: stdin: not in gzip format
tar: Child returned status 1
tar: Error is not recoverable: exiting now

zlib-1.3.tar.gz contains a 404 not found message in html format, it is not a tar.gz.

Replace line 48:
ZLIB_VERSION="zlib-1.3"
with
ZLIB_VERSION="zlib-1.3.1"

Appears to install correctly after this change.

Feature request: progress bar helpers when using --no-parallel-enum

I have notice that at the end of the execution there are very nice statistics in stderr. Would it be possible to output at the beginning the set of ciphers and versions and then for every test the combination tried? That way we could keep track of the percentage of test performed and implement a progress bar on top on your tool. Another option would be to do the percentage calculation internally and have another, e.g. --bar that shows the progress bar directly in stderr.

The recommended no. of concurrent workers

Hi, I would like to run tls-scan with --concurrency option set to perform the scan as fast as possible. The readme says:

Concurrency should be set based on your system capacity (memory, cpu, network) etc. Default: 1.

If I'm using Ubuntu 18 with 16 GB RAM and Intel Core i7 2.6 GHz processor, can you suggest the suitable value? Can you provide your experience values as guidance for selecting the most suitable value of this parameter?

Missing certificate chain and invalid JSON is produced with a dangling comma

I encountered an error while parsing the JSON produced by tls-scan and pinpointed it to a case where the certificate chain is missing from the JSON output and a dangling comma is left before closing the JSON object.

{ "host": "18.236.255.249", "ip": "18.236.255.249", "port": 443, "elapsedTime": 571, "tlsVersion": "TLSv1.2", "cipher": "ADH-AES256-SHA          SSLv3 Kx=DH       Au=None Enc=AES(256)  Mac=SHA1", "tempPublicKeyAlg": "DH", "tempPublicKeySize": 2048, "secureRenego": true, "compression": "NONE", "expansion": "NONE", "sessionLifetimeHint": 300, "x509ChainDepth": -1, "verifyCertResult": true, "verifyHostResult": false, "ocspStapled": false, }

To reproduce what i'm seeing you can try the following:

echo '18.236.255.249' | tls-scan | jq
parse error: Expected another key-value pair at line 1, column 441

GnuTLS Handshake Errors

Thanks for continuing the work on this tool. I just wanted to report an error I get when running scans, but it doesn't seem to effect the results.

host: hostname; ip: n.n.n.n; error: Network; errormsg: Error encountered during GnuTLS handshake: -12 Unsupported TLS 1.3 version/cipher

Any idea what this is? If you need more data, please advise how you would like it generated.

Thanks!
Randal

Incorrect `tlsVersions` in output

Hi there,

Unless I'm misinterpreting something the tlsVersions key seems to be incorrect.

./bin/tls-scan-1.4.8-darwin -c twitter.com --cacert cacert.pem --version-enum
{
    "host": "twitter.com",
    "ip": "104.244.42.193",
    "port": 443,
    "elapsedTime": 221,
    "tlsVersion": "TLSv1.2",
    "cipher": "ECDHE-ECDSA-AES128-GCM-SHA256 TLSv1.2 Kx=ECDH     Au=ECDSA Enc=AESGCM(128) Mac=AEAD",
    "tempPublicKeyAlg": "ECDH prime256v1",
    "tempPublicKeySize": 256,
    "secureRenego": true,
    "compression": "NONE",
    "expansion": "NONE",
    "sessionLifetimeHint": 7200,
    "tlsVersions": [
        "TLSv1_3"
    ],
    "x509ChainDepth": 2,
    "verifyCertResult": true,
    "verifyHostResult": true,
    "ocspStapled": false,
    "certificateChain": [
        {
            "version": 3,
            "subject": "CN=twitter.com; O=Twitter, Inc.; L=San Francisco; ST=California; C=US",
            "issuer": "CN=twitter.com; O=Twitter, Inc.; L=San Francisco; ST=California; C=US",
            "subjectCN": "twitter.com",
            "subjectAltName": "DNS:twitter.com, DNS:www.twitter.com",
            "signatureAlg": "ecdsa-with-SHA384",
            "notBefore": "Mar  7 00:00:00 2022 GMT",
            "notAfter": "Mar  6 23:59:59 2023 GMT",
            "expired": false,
            "serialNo": "02:93:C3:98:C2:CF:4A:67:BE:83:B5:37:54:DA:93:79",
            "keyUsage": "Digital Signature critical",
            "extKeyUsage": "TLS Web Server Authentication, TLS Web Client Authentication",
            "publicKeyAlg": "ECC prime256v1",
            "publicKeySize": 256,
            "basicConstraints": "CA:FALSE",
            "subjectKeyIdentifier": "23:2E:02:96:1A:49:3A:2E:52:84:60:D0:D3:C0:72:0A:8F:53:34:28",
            "sha1Fingerprint": "37:63:F4:77:39:1F:19:EF:D1:63:ED:67:74:1B:92:83:0F:9E:D4:93"
        },
        {
            "version": 3,
            "subject": "CN=DigiCert TLS Hybrid ECC SHA384 2020 CA1; O=DigiCert Inc; C=US",
            "issuer": "CN=DigiCert TLS Hybrid ECC SHA384 2020 CA1; O=DigiCert Inc; C=US",
            "subjectCN": "DigiCert TLS Hybrid ECC SHA384 2020 CA1",
            "signatureAlg": "sha384WithRSAEncryption",
            "notBefore": "Apr 14 00:00:00 2021 GMT",
            "notAfter": "Apr 13 23:59:59 2031 GMT",
            "expired": false,
            "serialNo": "07:F2:F3:5C:87:A8:77:AF:7A:EF:E9:47:99:35:25:BD",
            "keyUsage": "Digital Signature, Certificate Sign, CRL Sign critical",
            "extKeyUsage": "TLS Web Server Authentication, TLS Web Client Authentication",
            "publicKeyAlg": "ECC secp384r1",
            "publicKeySize": 384,
            "basicConstraints": "CA:TRUE, pathlen:0 critical",
            "subjectKeyIdentifier": "0A:BC:08:29:17:8C:A5:39:6D:7A:0E:CE:33:C7:2E:B3:ED:FB:C3:7A",
            "sha1Fingerprint": "AE:C1:3C:DD:5E:A6:A3:99:8A:EC:14:AC:33:1A:D9:6B:ED:BB:77:0F"
        }
    ]
}

tlsVersions only lists TLSv1_3 even though tlsVersion states 1.2 which Twitter also supports. So it's either missing TLSv1_2 from the list or I'm missing something obvious why it shouldn't be there :)

tls-scan installation failure

Hi @prbinu :)
i have followed all those steps to install tls-scan
installed gcc , autoconf , automake , libtool , pkg-config , git clone https://github.com/prbinu/tls-scan.git , cd tls-scan and ./build-x86-64.sh
but ended up with ./tls-scan command not found

  /usr/bin/install -c $f /root/tls-scan/build-root/bin ; \
done
make[1]: Leaving directory '/root/tls-scan/build-root/build/nettle-nettle_3.5.1_release_20190627/tools'
Making install in testsuite
make[1]: Entering directory '/root/tls-scan/build-root/build/nettle-nettle_3.5.1_release_20190627/testsuite'
true
make[1]: Leaving directory '/root/tls-scan/build-root/build/nettle-nettle_3.5.1_release_20190627/testsuite'
Making install in examples
make[1]: Entering directory '/root/tls-scan/build-root/build/nettle-nettle_3.5.1_release_20190627/examples'
true
make[1]: Leaving directory '/root/tls-scan/build-root/build/nettle-nettle_3.5.1_release_20190627/examples'
Downloading gnutls_3.6.10.
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:--  0:02:11 --:--:--     0curl: (7) Failed to connect to www.gnupg.org port 443: Connection timed out
./build-x86-64.sh: line 7: ./configure: No such file or directory
make: *** No targets specified and no makefile found.  Stop.
make: *** No rule to make target 'install'.  Stop.
>>> Complete

how can i fix that ?
i am running Ubuntu 18.04.4 LTS (GNU/Linux 4.15.0-66-generic x86_64) VPS from DigitalOcean

Regarding SSLv3 and TLSv1.1. in the parsed results

Hi,
I suspect there is some bug in recording the TLS version in the results (json file) or somewhere. Using tls-scan on a large set of addresses I get very high number of SSLv3 in the results (around 70%) which sounds unusual. The SSLv3 version code as far as I know is:
SSLv3: 0x00000300
TLS1.0: 0x00000301
TLS1.1: 0x00000302
TLS1.2: 0x00000303

Do you suspect any issue in parsing the server's selected version value (from the server hello)? I am using the tls-scan tool not for enumeration, just a regular handshake. I compiled my tls-scan using this .sh file (and I specified OpenSSL 1.1.0g):
https://github.com/prbinu/tls-scan/blob/master/build-x86-64-openssl-1.1.0.sh

Thanks.

Orphaned Sockets in FIN-WAIT-1 State Causing tls-scan to Halt

I have been encountering a significant issue while using tls-scan version 1.5.1 on Ubuntu 20.04 LTS to conduct scans against a large number of hosts. The tool seems to generate a substantial number of orphaned sockets during operation, leading to a state where it ceases to progress further. Notably, the tool doesn't crash, nor does it produce any error message. Instead, it just appears to stop executing without indication.

This problem becomes particularly evident when the ss -s command is executed, revealing thousands of sockets stuck in the FIN-WAIT-1 state. This excessive number of sockets in the FIN-WAIT-1 state, coupled with the system's kernel repeatedly logging "TCP: too many orphaned sockets," points to a bottleneck in the system's ability to manage these sockets.

Kernel log examples:

Apr 27 08:19:42 curious-rosetaupe-raven kernel: [ 5932.164427] TCP: too many orphaned sockets
Apr 27 08:20:28 curious-rosetaupe-raven kernel: [ 5978.499299] TCP: too many orphaned sockets
Apr 27 08:20:36 curious-rosetaupe-raven kernel: [ 5986.275047] TCP: too many orphaned sockets
Apr 27 08:20:39 curious-rosetaupe-raven kernel: [ 5990.115057] TCP: too many orphaned sockets
Apr 27 08:21:08 curious-rosetaupe-raven kernel: [ 6018.946519] TCP: too many orphaned sockets
Apr 27 08:22:00 curious-rosetaupe-raven kernel: [ 6070.657708] TCP: too many orphaned sockets
Apr 27 08:22:02 curious-rosetaupe-raven kernel: [ 6072.193706] TCP: too many orphaned sockets
Apr 27 08:22:04 curious-rosetaupe-raven kernel: [ 6074.337643] TCP: too many orphaned sockets

The accumulation of orphaned sockets, particularly those in the FIN-WAIT-1 state, seems to be directly related to tls-scan's halting issue. This becomes a significant problem when scanning larger sets of hosts. Any insights into mitigating the excessive generation of these orphaned sockets or advice on potential workarounds would be extremely beneficial.

Incorrect scan result with CHACHA cipher

Hi, I am sure (by manual testing from a browser that only supports: ecdhe_rsa_chacha20_poly1305_sha256) that "google.com" supports ecdhe_rsa_chacha20_poly1305_sha256.

However, when I perform a scan using: tls-scan, I do not get this cipher as a supported cipher by google.com. Can you please clarify the issue to me? CHACHA appears to be in the list of ciphers that tls-scan examined (according to the output) but this seems not the case.

Question on certificate validation

I am sorry that I seem to be misusing the issues section but if there is another way of communication, I will appreciate letting me know.

Just need a bit of clarification on the certificate and host validation process. Namely, the result of the:

"verifyCertResult": true,
"verifyHostResult": true
  1. For verifyCertResult I see in the code it calls:
    SSL_get_verify_result(ssl)
    Can you please clarify 1) which function makes the verification? Is it going to use the X509_verify_cert(), or is there anything else? 2) What it verifies exactly? e.g. signature, chain, etc. Can you specify what it verifies exactly for clarity please? and plz provide me with a link of the verification function that will be used from the library.

  2. Regarding the X509_check_host, does the certificate verification in the previous point includes host verification or not?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.