Skip to content

Commit 78df968

Browse files
committed
Throw error when incoming connection uses TLS, fix merge conflict
- Make remoteAddress and domain parameters optional since we don't have them available
1 parent 352ae83 commit 78df968

5 files changed

Lines changed: 28 additions & 32 deletions

File tree

src/workerd/api/global-scope.c++

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -140,21 +140,15 @@ kj::Promise<void> ServiceWorkerGlobalScope::connect(kj::String host,
140140
auto& ioContext = IoContext::current();
141141
jsg::Lock& js = lock;
142142

143-
auto input = kj::str("fake://", host);
144-
auto url = JSG_REQUIRE_NONNULL(
145-
jsg::Url::tryParse(input.asPtr()), TypeError, "Specified address could not be parsed.");
146-
auto hostName = url.getHostname();
147-
auto port = url.getPort();
148-
JSG_REQUIRE(hostName != ""_kj, TypeError, "Specified address is missing hostname.");
149-
JSG_REQUIRE(port != ""_kj, TypeError, "Specified address is missing port.");
150-
151-
// TLS support is not implemented so far.
143+
// TLS support is not implemented so far. Note that setupSocket() expects the domain parameter
144+
// to be set to the expected host name using startTLS, so that it can be provided to the TLS
145+
// callback, so we'd need to change that or figure out a way to get the host domain.
152146
auto nullTlsStarter = kj::heap<kj::TlsStarterCallback>();
153147
// We set isDefaultFetchPort to false here – sockets.c++ sets it for ports 443 and 8080 to
154148
// provide a more descriptive error message for HTTP, but this is not relevant on the TCP server
155149
// side.
156-
jsg::Ref<Socket> jsSocket = setupSocket(js, kj::mv(ownConnection), kj::mv(host), kj::none,
157-
kj::mv(nullTlsStarter), SecureTransportKind::OFF, kj::str(hostName), false, kj::none);
150+
jsg::Ref<Socket> jsSocket = setupSocket(js, kj::mv(ownConnection), kj::none, kj::none,
151+
kj::mv(nullTlsStarter), SecureTransportKind::OFF, kj::none, false, kj::none);
158152
// handleProxyStatus() is required to indicate that the socket was opened properly. Since the
159153
// connection is already open at this point, exception handling is not required.
160154
jsSocket->handleProxyStatus(js, kj::Promise<kj::Maybe<kj::Exception>>(kj::none));

src/workerd/api/sockets.c++

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,11 @@ class StreamWorkerInterface;
8484

8585
jsg::Ref<Socket> setupSocket(jsg::Lock& js,
8686
kj::Own<kj::AsyncIoStream> connection,
87-
kj::String remoteAddress,
87+
kj::Maybe<kj::String> remoteAddress,
8888
jsg::Optional<SocketOptions> options,
8989
kj::Own<kj::TlsStarterCallback> tlsStarter,
9090
SecureTransportKind secureTransport,
91-
kj::String domain,
91+
kj::Maybe<kj::String> domain,
9292
bool isDefaultFetchPort,
9393
kj::Maybe<jsg::PromiseResolverPair<SocketInfo>> maybeOpenedPrPair) {
9494
auto& ioContext = IoContext::current();
@@ -323,10 +323,10 @@ jsg::Ref<Socket> Socket::startTls(jsg::Lock& js, jsg::Optional<TlsOptions> tlsOp
323323
secureTransport != SecureTransportKind::ON, TypeError, "Cannot startTls on a TLS socket.");
324324
JSG_REQUIRE(connectionData != kj::none, TypeError,
325325
"The connection was closed before startTls could be started.");
326-
JSG_REQUIRE(domain != nullptr, TypeError, "startTls can only be called once.");
327326
auto invalidOptKindMsg =
328327
"The `secureTransport` socket option must be set to 'starttls' for startTls to be used.";
329328
JSG_REQUIRE(secureTransport == SecureTransportKind::STARTTLS, TypeError, invalidOptKindMsg);
329+
JSG_REQUIRE(domain != kj::none, TypeError, "startTls can only be called once.");
330330

331331
// The current socket's writable buffers need to be flushed. The socket's WritableStream is backed
332332
// by an AsyncIoStream which doesn't implement any buffering, so we don't need to worry about
@@ -346,10 +346,10 @@ jsg::Ref<Socket> Socket::startTls(jsg::Lock& js, jsg::Optional<TlsOptions> tlsOp
346346
// flush to complete. While it is unlikely to be GC'd while we are waiting because
347347
// the user code *likely* is holding a active reference to it at this point, we
348348
// don't want to take any chances. This prevents a possible UAF.
349-
JSG_VISITABLE_LAMBDA(
350-
(self = JSG_THIS, domain = kj::heapString(domain), tlsOptions = kj::mv(tlsOptions),
351-
openedResolver = openedPrPair.resolver.addRef(js),
352-
remoteAddress = kj::str(remoteAddress)),
349+
JSG_VISITABLE_LAMBDA((self = JSG_THIS, domain = kj::heapString(KJ_ASSERT_NONNULL(domain)),
350+
tlsOptions = kj::mv(tlsOptions),
351+
openedResolver = openedPrPair.resolver.addRef(js),
352+
remoteAddress = mapCopyString(remoteAddress)),
353353
(self, openedResolver), (jsg::Lock & js) mutable {
354354
auto& context = IoContext::current();
355355

@@ -381,7 +381,7 @@ jsg::Ref<Socket> Socket::startTls(jsg::Lock& js, jsg::Optional<TlsOptions> tlsOp
381381

382382
// Fork the starter promise because we need to create two separate things waiting
383383
// on it below. The first is resolving the openedResolver with a JS promise that
384-
// wraps one branch, the secnod is the kj::Promise that we use to resolve the
384+
// wraps one branch, the second is the kj::Promise that we use to resolve the
385385
// secureStream for the promised stream. This keeps us from having to bounce in and
386386
// out of the JS isolate lock.
387387
auto forkedPromise = KJ_ASSERT_NONNULL(*tlsStarter)(acceptedHostname).fork();
@@ -410,9 +410,9 @@ jsg::Ref<Socket> Socket::startTls(jsg::Lock& js, jsg::Optional<TlsOptions> tlsOp
410410
// The existing tlsStarter gets consumed and we won't need it again. Pass in an empty tlsStarter
411411
// to `setupSocket`.
412412
auto newTlsStarter = kj::heap<kj::TlsStarterCallback>();
413-
return setupSocket(js, kj::newPromisedStream(kj::mv(secureStreamPromise)), kj::str(remoteAddress),
414-
kj::mv(options), kj::mv(newTlsStarter), SecureTransportKind::ON, kj::mv(domain),
415-
isDefaultFetchPort, kj::mv(openedPrPair));
413+
return setupSocket(js, kj::newPromisedStream(kj::mv(secureStreamPromise)),
414+
mapCopyString(remoteAddress), kj::mv(options), kj::mv(newTlsStarter), SecureTransportKind::ON,
415+
kj::mv(domain), isDefaultFetchPort, kj::mv(openedPrPair));
416416
}
417417

418418
void Socket::handleProxyStatus(
@@ -436,7 +436,7 @@ void Socket::handleProxyStatus(
436436
if (isDefaultFetchPort) {
437437
msg = kj::str(msg, ". It looks like you might be trying to connect to a HTTP-based service",
438438
" — consider using fetch instead");
439-
} else if (remoteAddress.contains(".hyperdrive.local"_kj)) {
439+
} else if (remoteAddress.orDefault(kj::String()).contains(".hyperdrive.local"_kj)) {
440440
// No attempts to connect to Hyperdrive should end up here, since they go through the other
441441
// version of handleProxyStatus. If they end up here somehow, log about it to get some
442442
// context that can aid in debugging.
@@ -450,7 +450,7 @@ void Socket::handleProxyStatus(
450450
// because there's no useful value we can provide.
451451
openedResolver.resolve(js,
452452
SocketInfo{
453-
.remoteAddress = kj::str(remoteAddress),
453+
.remoteAddress = mapCopyString(remoteAddress),
454454
.localAddress = kj::none,
455455
});
456456
}
@@ -478,7 +478,7 @@ void Socket::handleProxyStatus(jsg::Lock& js, kj::Promise<kj::Maybe<kj::Exceptio
478478
// because there's no useful value we can provide.
479479
openedResolver.resolve(js,
480480
SocketInfo{
481-
.remoteAddress = kj::str(remoteAddress),
481+
.remoteAddress = mapCopyString(remoteAddress),
482482
.localAddress = kj::none,
483483
});
484484
}

src/workerd/api/sockets.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,15 +60,15 @@ class Socket: public jsg::Object {
6060
Socket(jsg::Lock& js,
6161
IoContext& context,
6262
kj::Own<kj::RefcountedWrapper<kj::Own<kj::AsyncIoStream>>> connectionStream,
63-
kj::String remoteAddress,
63+
kj::Maybe<kj::String> remoteAddress,
6464
jsg::Ref<ReadableStream> readableParam,
6565
jsg::Ref<WritableStream> writable,
6666
jsg::PromiseResolverPair<void> closedPrPair,
6767
kj::Promise<void> watchForDisconnectTask,
6868
jsg::Optional<SocketOptions> options,
6969
kj::Own<kj::TlsStarterCallback> tlsStarter,
7070
SecureTransportKind secureTransport,
71-
kj::String domain,
71+
kj::Maybe<kj::String> domain,
7272
bool isDefaultFetchPort,
7373
jsg::PromiseResolverPair<SocketInfo> openedPrPair)
7474
: connectionData(context.addObject(kj::heap<ConnectionData>(
@@ -200,12 +200,12 @@ class Socket: public jsg::Object {
200200
// Memoized copy that is returned by the `closed` attribute.
201201
jsg::MemoizedIdentity<jsg::Promise<void>> closedPromise;
202202
jsg::Optional<SocketOptions> options;
203-
kj::String remoteAddress;
203+
kj::Maybe<kj::String> remoteAddress;
204204
// Set to true when the socket is upgraded to a secure one.
205205
bool upgraded = false;
206206
SecureTransportKind secureTransport;
207207
// The domain/ip this socket is connected to. Used for startTls.
208-
kj::String domain;
208+
kj::Maybe<kj::String> domain;
209209
// Whether the port this socket connected to is 80/443. Used for nicer errors.
210210
bool isDefaultFetchPort;
211211
// This fulfiller is used to resolve the `openedPromise` below.
@@ -245,11 +245,11 @@ class Socket: public jsg::Object {
245245

246246
jsg::Ref<Socket> setupSocket(jsg::Lock& js,
247247
kj::Own<kj::AsyncIoStream> connection,
248-
kj::String remoteAddress,
248+
kj::Maybe<kj::String> remoteAddress,
249249
jsg::Optional<SocketOptions> options,
250250
kj::Own<kj::TlsStarterCallback> tlsStarter,
251251
SecureTransportKind secureTransport,
252-
kj::String domain,
252+
kj::Maybe<kj::String> domain,
253253
bool isDefaultFetchPort,
254254
kj::Maybe<jsg::PromiseResolverPair<SocketInfo>> maybeOpenedPrPair);
255255

src/workerd/io/worker-entrypoint.c++

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -565,6 +565,8 @@ kj::Promise<void> WorkerEntrypoint::connect(kj::StringPtr host,
565565
JSG_FAIL_REQUIRE(TypeError, "Incoming CONNECT on a worker not supported");
566566
}
567567

568+
// TODO(soon): Implement basic TLS support for connect handler.
569+
JSG_REQUIRE(!settings.useTls, Error, "Incoming CONNECT with TLS not supported");
568570
// Capture workerTracer, see request() for rationale.
569571
kj::Maybe<BaseTracer&> workerTracer;
570572

src/workerd/io/worker-interface.capnp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ struct Trace @0x8e8d911203762d34 {
9797
email @16 :EmailEventInfo;
9898
trace @18 :TraceEventInfo;
9999
hibernatableWebSocket @20 :HibernatableWebSocketEventInfo;
100-
connect @28 :ConnectEventInfo;
100+
connect @29 :ConnectEventInfo;
101101
}
102102
struct FetchEventInfo {
103103
method @0 :HttpMethod;

0 commit comments

Comments
 (0)