Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions src/FtpContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ export class FTPContext {
ipFamily: number | undefined = undefined
/** Options for TLS connections. */
tlsOptions: TLSConnectionOptions = {}
/** Most recent TLS session from the control connection, used to resume the session on data connections. */
tlsSessionStore: Buffer | undefined = undefined
/** Current task to be resolved or rejected. */
protected _task: Task | undefined
/** A multiline response might be received as multiple chunks. */
Expand Down Expand Up @@ -150,6 +152,7 @@ export class FTPContext {
this.dataSocket = undefined
// This being a reset, reset any other state apart from the socket.
this.tlsOptions = {}
this.tlsSessionStore = undefined
this._partialResponse = ""
if (this._socket) {
const newSocketUpgradesExisting = socket.localPort === this._socket.localPort
Expand All @@ -175,6 +178,9 @@ export class FTPContext {
// Control being closed without error by server is treated as an error.
socket.on("close", hadError => { if (!hadError) this.closeWithError(new Error("Server closed connection unexpectedly.")) })
this._setupDefaultErrorHandlers(socket, "control socket")
if (socket instanceof TLSSocket) {
socket.on("session", session => { this.tlsSessionStore = session })
}
}
this._socket = socket
}
Expand Down
6 changes: 5 additions & 1 deletion src/transfer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,12 @@ export function connectForPassiveTransfer(host: string, port: number, ftp: FTPCo
// security: If a completely new session would be negotiated, a hacker
// could guess the port and connect to the new data connection before we do
// by just starting his/her own TLS session.
session: ftp.socket.getSession()
session: ftp.tlsSessionStore ?? ftp.socket.getSession()
}))
// When the server issues a new session ticket after this data connection's
// TLS handshake (TLS 1.3 single-use tickets), capture it so the next data
// connection can present a fresh ticket and resume successfully.
socket.on("session", session => { ftp.tlsSessionStore = session })
// It's the responsibility of the transfer task to wait until the
// TLS socket issued the event 'secureConnect'. We can't do this
// here because some servers will start upgrading after the
Expand Down
Loading