Skip to content

Commit a91f2bb

Browse files
committed
GH-71 Expose rest of SSL_CTX_set_client_hello_cb family of functions.
Also update tests in 48_client_hello_callback.t and documentation in SSLeay.pod.
1 parent b68240c commit a91f2bb

File tree

4 files changed

+321
-6
lines changed

4 files changed

+321
-6
lines changed

Changes

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,29 @@ Revision history for Perl extension Net::SSLeay.
3030
Update the previous minor releases to their latest versions. Add
3131
NetBSD to BSDs job and update the other BSDs and Alpine Linux jobs to
3232
cover additional and latest releases. Use the latest MacOS runners.
33+
- Expose SSL_CTX_set_client_hello_cb for setting a callback
34+
the server calls when it processes a ClientHello. Expose the
35+
following functions that can be called only from the
36+
callback.
37+
- SSL_client_hello_isv2
38+
- SSL_client_hello_get0_legacy_version
39+
- SSL_client_hello_get0_random
40+
- SSL_client_hello_get0_session_id
41+
- SSL_client_hello_get0_ciphers
42+
- SSL_client_hello_get0_compression_methods
43+
- SSL_client_hello_get1_extensions_present
44+
- SSL_client_hello_get_extension_order
45+
- SSL_client_hello_get0_ext
46+
- Expose constants used by SSL_CTX_set_client_hello_cb related
47+
functions:
48+
- AD_ prefixed constants naming TLS alert codes for
49+
returning from a ClientHello callback or where alert types
50+
are used
51+
- CLIENT_HELLO_ERROR, CLIENT_HELLO_RETRY and
52+
CLIENT_HELLO_SUCCESS for returning from a ClientHello
53+
callback
54+
- TLSEXT_TYPE_ prefixed contants for naming TLS extension
55+
types
3356

3457
1.93_02 2023-02-22
3558
- Update ppport.h to version 3.68. This eliminates thousands of

SSLeay.xs

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5896,6 +5896,112 @@ SSL_CTX_set_client_hello_cb(SSL_CTX *ctx, SV *callback, SV *arg=&PL_sv_undef)
58965896
int
58975897
SSL_client_hello_isv2(SSL *s)
58985898

5899+
unsigned int
5900+
SSL_client_hello_get0_legacy_version(SSL *s)
5901+
5902+
void
5903+
SSL_client_hello_get0_random(SSL *s)
5904+
PREINIT:
5905+
const unsigned char *out = NULL;
5906+
size_t outlen;
5907+
CODE:
5908+
outlen = SSL_client_hello_get0_random(s, &out);
5909+
if (outlen == 0) XSRETURN_PV("");
5910+
ST(0) = sv_newmortal();
5911+
sv_setpvn(ST(0), (const char *)out, (STRLEN)outlen);
5912+
5913+
void
5914+
SSL_client_hello_get0_session_id(SSL *s)
5915+
PREINIT:
5916+
const unsigned char *out = NULL;
5917+
size_t outlen;
5918+
CODE:
5919+
outlen = SSL_client_hello_get0_session_id(s, &out);
5920+
if (outlen == 0) XSRETURN_PV("");
5921+
ST(0) = sv_newmortal();
5922+
sv_setpvn(ST(0), (const char *)out, (STRLEN)outlen);
5923+
5924+
void
5925+
SSL_client_hello_get0_ciphers(SSL *s)
5926+
PREINIT:
5927+
const unsigned char *out = NULL;
5928+
size_t outlen;
5929+
CODE:
5930+
outlen = SSL_client_hello_get0_ciphers(s, &out);
5931+
if (outlen == 0) XSRETURN_PV("");
5932+
ST(0) = sv_newmortal();
5933+
sv_setpvn(ST(0), (const char *)out, (STRLEN)outlen);
5934+
5935+
void
5936+
SSL_client_hello_get0_compression_methods(SSL *s)
5937+
PREINIT:
5938+
const unsigned char *out = NULL;
5939+
size_t outlen;
5940+
CODE:
5941+
outlen = SSL_client_hello_get0_compression_methods(s, &out);
5942+
if (outlen == 0) XSRETURN_PV("");
5943+
ST(0) = sv_newmortal();
5944+
sv_setpvn(ST(0), (const char *)out, (STRLEN)outlen);
5945+
5946+
void
5947+
SSL_client_hello_get1_extensions_present(SSL *s)
5948+
PREINIT:
5949+
int ret, *out = NULL, i;
5950+
size_t outlen;
5951+
AV *av;
5952+
PPCODE:
5953+
ret = SSL_client_hello_get1_extensions_present(s, &out, &outlen);
5954+
if (ret != 1) XSRETURN_UNDEF;
5955+
5956+
av = newAV();
5957+
mXPUSHs(newRV_noinc((SV*)av));
5958+
for (i=0; i < outlen; i++) {
5959+
av_push(av, newSViv(*(out + i)));
5960+
}
5961+
OPENSSL_free(out);
5962+
5963+
#if OPENSSL_VERSION_NUMBER >= 0x30200000L && !defined(LIBRESSL_VERSION_NUMBER)
5964+
5965+
void
5966+
SSL_client_hello_get_extension_order(SSL *s)
5967+
PREINIT:
5968+
int ret, i;
5969+
uint16_t *exts;
5970+
size_t num_exts;
5971+
AV *av;
5972+
PPCODE:
5973+
ret = SSL_client_hello_get_extension_order(s, NULL, &num_exts);
5974+
if (ret != 1) XSRETURN_UNDEF;
5975+
5976+
Newx(exts, num_exts, uint16_t);
5977+
ret = SSL_client_hello_get_extension_order(s, exts, &num_exts);
5978+
if (ret != 1) {
5979+
Safefree(exts);
5980+
XSRETURN_UNDEF;
5981+
}
5982+
5983+
av = newAV();
5984+
mXPUSHs(newRV_noinc((SV*)av));
5985+
for (i=0; i < num_exts; i++) {
5986+
av_push(av, newSViv(*(exts + i)));
5987+
}
5988+
Safefree(exts);
5989+
5990+
#endif
5991+
5992+
void
5993+
SSL_client_hello_get0_ext(SSL *s, unsigned int type)
5994+
PREINIT:
5995+
int ret;
5996+
const unsigned char *out = NULL;
5997+
size_t outlen;
5998+
CODE:
5999+
ret = SSL_client_hello_get0_ext(s, type, &out, &outlen);
6000+
if (ret != 1) XSRETURN_UNDEF;
6001+
6002+
ST(0) = sv_newmortal();
6003+
sv_setpvn(ST(0), (const char *)out, (STRLEN)outlen);
6004+
58996005
#endif
59006006

59016007
int

lib/Net/SSLeay.pod

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5510,6 +5510,91 @@ Indicate if the ClientHello was carried in a SSLv2 record and is in the SSLv2 fo
55105510

55115511
Check openssl doc L<https://www.openssl.org/docs/manmaster/man3/SSL_client_hello_isv2.html>
55125512

5513+
=item * client_hello_get0_legacy_version
5514+
5515+
B<COMPATIBILITY:> not available in Net-SSLeay-1.92 and before; requires at least OpenSSL 1.1.1pre1, not in LibreSSL
5516+
5517+
B<NOTE:> to be used only from a callback set with L<CTX_set_client_hello_cb>.
5518+
5519+
Returns legacy_version, also known as client_version, field from the ClientHello.
5520+
5521+
my $rv = client_hello_get0_legacy_version($s);
5522+
# $s - value corresponding to openssl's SSL structure
5523+
#
5524+
# returns: unsigned integer, for example 0x0303 (TLS v1.2) with TLS 1.3
5525+
5526+
Check openssl doc L<https://www.openssl.org/docs/manmaster/man3/SSL_client_hello_get0_legacy_version.html>
5527+
5528+
=item * client_hello_get0_random, client_hello_get0_session_id, client_hello_get0_ciphers and client_hello_get0_compression_methods
5529+
5530+
B<COMPATIBILITY:> not available in Net-SSLeay-1.92 and before; requires at least OpenSSL 1.1.1pre1, not in LibreSSL
5531+
5532+
B<NOTE:> to be used only from a callback set with L<CTX_set_client_hello_cb>.
5533+
5534+
These functions return random, session_id, cipher_suites and compression_methods fields from the ClientHello, respectively.
5535+
5536+
my $random = client_hello_get0_random($s);
5537+
my $session_id = client_hello_get0_session_id($s);
5538+
my $ciphers = client_hello_get0_ciphers($s);
5539+
my $compression_methods = client_hello_get0_compression_methods($s);
5540+
# $s - value corresponding to openssl's SSL structure
5541+
#
5542+
# returns: raw octet data where data length, zero or more, depends on the field definition
5543+
5544+
Check openssl doc L<https://www.openssl.org/docs/manmaster/man3/SSL_client_hello_get0_random.html>
5545+
5546+
=item * client_hello_get1_extensions_present and client_hello_get_extension_order
5547+
5548+
B<COMPATIBILITY:> not available in Net-SSLeay-1.92 and before; requires at least OpenSSL 1.1.1pre1, not in LibreSSL
5549+
5550+
B<NOTE:> to be used only from a callback set with L<CTX_set_client_hello_cb>.
5551+
5552+
Returns a reference to an array holding the numerical value of the TLS extension types in the order they appear in the ClientHello. client_hello_get_extension_order is similar and requires at least OpenSSL 3.2.0, not in LibreSSL.
5553+
5554+
my $ref = client_hello_get1_extensions_present($s);
5555+
# $s - value corresponding to openssl's SSL structure
5556+
#
5557+
# returns: an array reference of zero or more extension types or undef on failure
5558+
5559+
Example from a TLS 1.3 ClientHello:
5560+
5561+
sub client_hello_cb {
5562+
my ($ssl, $arg) = @_;
5563+
my $ref = client_hello_get1_extensions_present($ssl);
5564+
print join(' ', @$ref), "\n" if $ref;
5565+
}
5566+
5567+
Prints: C<11 10 35 22 23 13 43 45 51>
5568+
5569+
Check openssl doc L<https://www.openssl.org/docs/manmaster/man3/SSL_client_hello_get1_extensions_present.html>
5570+
5571+
5572+
=item * client_hello_get0_ext
5573+
5574+
B<COMPATIBILITY:> not available in Net-SSLeay-1.92 and before; requires at least OpenSSL 1.1.1pre1, not in LibreSSL
5575+
5576+
B<NOTE:> to be used only from a callback set with L<CTX_set_client_hello_cb>.
5577+
5578+
Returns an extension by type number from the ClientHello.
5579+
5580+
my $ref = client_hello_get1_extensions_present($s, $type);
5581+
# $s - value corresponding to openssl's SSL structure
5582+
# $type - (integer) extension type number
5583+
#
5584+
# returns: zero or more octets of extension contents including extension length, undef if the extension is not present
5585+
5586+
Example: Get the value of TLS extension C<supported_versions>. You can use constant C<TLSEXT_TYPE_supported_versions> or 43 directly.
5587+
5588+
sub client_hello_cb {
5589+
my ($ssl, $arg) = @_;
5590+
my $ext_ver = Net::SSLeay::client_hello_get0_ext($ssl, Net::SSLeay::TLSEXT_TYPE_supported_versions());
5591+
print unpack('H*', $ext_ver), "\n" if defined $ext_ver;
5592+
}
5593+
5594+
Prints: C<080304030303020301> where the first octet 0x08 is the extension length and the following four 16bit values correspond to TLS versions 1.3, 1.2, 1.1 and 1.0.
5595+
5596+
Check openssl doc L<https://www.openssl.org/docs/manmaster/man3/SSL_client_hello_get0_ext.html>
5597+
55135598
=back
55145599

55155600
=head3 Low level API: RAND_* related functions

0 commit comments

Comments
 (0)