diff --git a/src/main/java/com/google/devtools/build/lib/server/GrpcServerImpl.java b/src/main/java/com/google/devtools/build/lib/server/GrpcServerImpl.java index 5a8539e1fff270..8281eeda65e58c 100644 --- a/src/main/java/com/google/devtools/build/lib/server/GrpcServerImpl.java +++ b/src/main/java/com/google/devtools/build/lib/server/GrpcServerImpl.java @@ -64,6 +64,7 @@ import java.io.OutputStream; import java.net.InetSocketAddress; import java.nio.charset.StandardCharsets; +import java.security.MessageDigest; import java.security.SecureRandom; import java.util.Optional; import java.util.concurrent.Executor; @@ -473,7 +474,7 @@ private void writeServerFile(String name, String contents) throws AbruptExitExce } private void executeCommand(RunRequest request, BlockingStreamObserver observer) { - boolean badCookie = !request.getCookie().equals(requestCookie); + boolean badCookie = !isValidRequestCookie(request.getCookie()); if (badCookie || request.getClientDescription().isEmpty()) { try { FailureDetail failureDetail = @@ -616,7 +617,7 @@ public void run(final RunRequest request, final StreamObserver obse public void ping(PingRequest pingRequest, StreamObserver streamObserver) { try (RunningCommand command = commandManager.createCommand()) { PingResponse.Builder response = PingResponse.newBuilder(); - if (pingRequest.getCookie().equals(requestCookie)) { + if (isValidRequestCookie(pingRequest.getCookie())) { response.setCookie(responseCookie); } @@ -629,7 +630,7 @@ public void ping(PingRequest pingRequest, StreamObserver streamObs public void cancel( final CancelRequest request, final StreamObserver streamObserver) { logger.atInfo().log("Got CancelRequest for command id %s", request.getCommandId()); - if (!request.getCookie().equals(requestCookie)) { + if (!isValidRequestCookie(request.getCookie())) { streamObserver.onCompleted(); return; } @@ -651,6 +652,17 @@ private void doCancel(CancelRequest request, StreamObserver stre } } + /** + * Returns whether or not the provided cookie is valid for this server using a constant-time + * comparison in order to guard against timing attacks. + */ + private boolean isValidRequestCookie(String incomingRequestCookie) { + // Note that cookie file was written as latin-1, so use that here. + return MessageDigest.isEqual( + incomingRequestCookie.getBytes(StandardCharsets.ISO_8859_1), + requestCookie.getBytes(StandardCharsets.ISO_8859_1)); + } + private static AbruptExitException createFilesystemFailureException( String message, IOException e) { return new AbruptExitException(