Skip to content

Commit 925bfb3

Browse files
authored
Allow BuildHandshakeState to inspect ClientHello before setting SessionTicket/PSK (#301)
* Lock sessionController only on last call to BuildHandshakeState * Add public getter/setter for SessionState.extMasterSecret * Fix breaking exported MakeClientSessionState * Revert `(*UConn).BuildHandshakeState` to lock session controller This partially reverts ebe5d66 and introduces BuildHandshakeStateWithoutSession. * fix: Marshal the Client Hello after loading session --------- Signed-off-by: Gaukas Wang <[email protected]>
1 parent 4f71339 commit 925bfb3

File tree

2 files changed

+38
-6
lines changed

2 files changed

+38
-6
lines changed

u_conn.go

+24-6
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,23 @@ func UClient(conn net.Conn, config *Config, clientHelloID ClientHelloID) *UConn
8383
// [each call] marshal ClientHello.
8484
//
8585
// BuildHandshakeState is automatically called before uTLS performs handshake,
86-
// amd should only be called explicitly to inspect/change fields of
86+
// and should only be called explicitly to inspect/change fields of
8787
// default/mimicked ClientHello.
88+
// With the excpetion of session ticket and psk extensions, which cannot be changed
89+
// after calling BuildHandshakeState, all other fields can be modified.
8890
func (uconn *UConn) BuildHandshakeState() error {
91+
return uconn.buildHandshakeState(true)
92+
}
93+
94+
// BuildHandshakeStateWithoutSession is the same as BuildHandshakeState, but does not
95+
// set the session. This is only useful when you want to inspect the ClientHello before
96+
// setting the session manually through SetSessionTicketExtension or SetPSKExtension.
97+
// BuildHandshakeState is automatically called before uTLS performs handshake.
98+
func (uconn *UConn) BuildHandshakeStateWithoutSession() error {
99+
return uconn.buildHandshakeState(false)
100+
}
101+
102+
func (uconn *UConn) buildHandshakeState(loadSession bool) error {
89103
if uconn.ClientHelloID == HelloGolang {
90104
if uconn.clientHelloBuildStatus == BuildByGoTLS {
91105
return nil
@@ -125,19 +139,23 @@ func (uconn *UConn) BuildHandshakeState() error {
125139
return err
126140
}
127141

128-
err = uconn.uLoadSession()
129-
if err != nil {
130-
return err
142+
if loadSession {
143+
err = uconn.uLoadSession()
144+
if err != nil {
145+
return err
146+
}
131147
}
132148

133149
err = uconn.MarshalClientHello()
134150
if err != nil {
135151
return err
136152
}
137153

138-
uconn.uApplyPatch()
154+
if loadSession {
155+
uconn.uApplyPatch()
156+
uconn.sessionController.finalCheck()
157+
}
139158

140-
uconn.sessionController.finalCheck()
141159
uconn.clientHelloBuildStatus = BuildByUtls
142160
}
143161
return nil

u_public.go

+14
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,9 @@ func (PSS PskIdentities) ToPrivate() []pskIdentity {
617617

618618
// ClientSessionState is public, but all its fields are private. Let's add setters, getters and constructor
619619

620+
// TODO! can we change this enought (or export SessionState),
621+
// such that we wouldn't need to fork crypto/tls?
622+
620623
// ClientSessionState contains the state needed by clients to resume TLS sessions.
621624
func MakeClientSessionState(
622625
SessionTicket []uint8,
@@ -625,6 +628,7 @@ func MakeClientSessionState(
625628
MasterSecret []byte,
626629
ServerCertificates []*x509.Certificate,
627630
VerifiedChains [][]*x509.Certificate) *ClientSessionState {
631+
// TODO: Add EMS to this constructor in uTLS v2
628632
css := &ClientSessionState{
629633
ticket: SessionTicket,
630634
session: &SessionState{
@@ -658,6 +662,10 @@ func (css *ClientSessionState) MasterSecret() []byte {
658662
return css.session.secret
659663
}
660664

665+
func (css *ClientSessionState) EMS() bool {
666+
return css.session.extMasterSecret
667+
}
668+
661669
// Certificate chain presented by the server
662670
func (css *ClientSessionState) ServerCertificates() []*x509.Certificate {
663671
return css.session.peerCertificates
@@ -689,6 +697,12 @@ func (css *ClientSessionState) SetMasterSecret(MasterSecret []byte) {
689697
}
690698
css.session.secret = MasterSecret
691699
}
700+
func (css *ClientSessionState) SetEMS(ems bool) {
701+
if css.session == nil {
702+
css.session = &SessionState{}
703+
}
704+
css.session.extMasterSecret = ems
705+
}
692706
func (css *ClientSessionState) SetServerCertificates(ServerCertificates []*x509.Certificate) {
693707
if css.session == nil {
694708
css.session = &SessionState{}

0 commit comments

Comments
 (0)