Skip to content

Commit debcc0f

Browse files
authored
Merge pull request #335 from jtesta/handshake_backup. Fixes #334
Add Handshake Backup When Primary Protocol Detection Fails
2 parents 131763e + 6184b83 commit debcc0f

File tree

2 files changed

+104
-0
lines changed

2 files changed

+104
-0
lines changed

‎sslscan.c‎

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4962,6 +4962,109 @@ unsigned int checkIfTLSVersionIsSupported(struct sslCheckOptions *options, unsig
49624962
bs_free(&tls_extensions);
49634963
bs_free(&client_hello);
49644964
bs_free(&server_hello);
4965+
4966+
/* If we're about to return false, let's make one last attempt using OpenSSL's built-in functions to test the protocol. Some non-standard TLS stacks don't like our ClientHello because it includes "too many" ciphersuite options (even though it is perfectly valid per the specs). */
4967+
if (ret == false)
4968+
ret = checkIfTLSVersionIsSupported_Backup(options, tls_version);
4969+
4970+
return ret;
4971+
}
4972+
4973+
/* Makes a fallback attempt to check if a TLS version is supported. Uses OpenSSL's functions instead of building our own ClientHello. Useful in odd cases where non-standard TLS stacks reject our valid ClientHellos. */
4974+
unsigned int checkIfTLSVersionIsSupported_Backup(struct sslCheckOptions *options, unsigned int tls_version) {
4975+
4976+
int ret = false;
4977+
int version = -1;
4978+
const SSL_METHOD *sslMethod = NULL;
4979+
4980+
/* Determine the right client method, ciphersuite list, and TLS version we need to work with. */
4981+
strncpy(options->cipherstring, CIPHERSUITE_LIST_ALL, sizeof(options->cipherstring) - 1);
4982+
if (tls_version == TLSv1_0) {
4983+
sslMethod = TLSv1_client_method();
4984+
version = TLS1_VERSION;
4985+
} else if (tls_version == TLSv1_1) {
4986+
sslMethod = TLSv1_1_client_method();
4987+
version = TLS1_1_VERSION;
4988+
} else if (tls_version == TLSv1_2) {
4989+
sslMethod = TLSv1_2_client_method();
4990+
version = TLS1_2_VERSION;
4991+
} else if (tls_version == TLSv1_3) {
4992+
sslMethod = TLSv1_3_client_method();
4993+
version = TLS1_3_VERSION;
4994+
strncpy(options->cipherstring, TLSV13_CIPHERSUITES, sizeof(options->cipherstring) - 1);
4995+
}
4996+
4997+
if (sslMethod == NULL)
4998+
goto done;
4999+
5000+
printf_verbose("Using fallback method for checking if %s is supported.\n", getPrintableTLSName(tls_version));
5001+
5002+
/* Connect to the target host. */
5003+
int socketDescriptor = tcpConnect(options);
5004+
if (socketDescriptor == 0) {
5005+
printf_verbose("%s: failed to connect to target.\n", __func__);
5006+
goto done;
5007+
}
5008+
5009+
/* Create a new context. */
5010+
options->ctx = new_CTX(sslMethod);
5011+
if (options->ctx == NULL) {
5012+
printf_verbose("%s: failed to create context.\n", __func__);
5013+
goto done;
5014+
}
5015+
5016+
/* Set the minimum and maximum protocol versions to the same thing. This ensures that if we connect, we're only connected with this exact TLS version. */
5017+
if (!SSL_CTX_set_min_proto_version(options->ctx, version)) {
5018+
printf_verbose("%s: failed to set minimum protocol version.\n", __func__);
5019+
goto done;
5020+
}
5021+
5022+
if (!SSL_CTX_set_max_proto_version(options->ctx, version)) {
5023+
printf_verbose("%s: failed to set maximum protocol version.\n", __func__);
5024+
goto done;
5025+
}
5026+
5027+
/* Set the ciphersuite string in the context. */
5028+
if (!setCipherSuite(options, sslMethod, options->cipherstring)) {
5029+
printf_verbose("%s: failed to set the ciphersuite list: [%s]\n", __func__, options->cipherstring);
5030+
goto done;
5031+
}
5032+
5033+
/* Create the SSL object. */
5034+
SSL *ssl = new_SSL(options->ctx);
5035+
if (ssl == NULL) {
5036+
printf_verbose("%s: failed to create SSL object.\n", __func__);
5037+
goto done;
5038+
}
5039+
5040+
/* Set the SNI. */
5041+
if (!SSL_set_tlsext_host_name(ssl, options->sniname)) {
5042+
printf_verbose("%s: failed to set SNI.\n", __func__);
5043+
goto done;
5044+
}
5045+
5046+
/* Wrap the raw socket with a new BIO. */
5047+
BIO *bio = BIO_new_socket(socketDescriptor, BIO_NOCLOSE);
5048+
if (bio == NULL) {
5049+
printf_verbose("%s: failed to create BIO socket.\n", __func__);
5050+
goto done;
5051+
}
5052+
5053+
SSL_set_bio(ssl, bio, bio);
5054+
5055+
/* Start the TLS handshake. */
5056+
int connStatus = SSL_connect(ssl);
5057+
if (connStatus == 1) {
5058+
ret = true;
5059+
printf_verbose("Backup connection succeeded for %s!\n", getPrintableTLSName(tls_version));
5060+
} else {
5061+
printf_verbose("%s: backup connection failed: %d\n", __func__, SSL_get_error(ssl, connStatus));
5062+
}
5063+
5064+
done:
5065+
CLOSE(socketDescriptor);
5066+
FREE_CTX(options->ctx);
5067+
FREE_SSL(ssl);
49655068
return ret;
49665069
}
49675070

‎sslscan.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,7 @@ void bs_set_byte(bs *, size_t, unsigned char);
318318
void bs_set_ushort(bs *b, size_t offset, unsigned short length);
319319
int bs_read_socket(bs *b, int s, size_t num_bytes);
320320
unsigned int checkIfTLSVersionIsSupported(struct sslCheckOptions *options, unsigned int tls_version);
321+
unsigned int checkIfTLSVersionIsSupported_Backup(struct sslCheckOptions *options, unsigned int tls_version);
321322
SSL_CTX *CTX_new(const SSL_METHOD *method);
322323
int fileExists(char *);
323324
void findMissingCiphers();

0 commit comments

Comments
 (0)