Skip to content

Commit

Permalink
Cleanup typing for password callbacks
Browse files Browse the repository at this point in the history
Although this adds two more classes, removing type hacks is likely
better.
Also essentially removes the default password callback since right now I
don't see where it is used. Will test further if anything bad happens.
  • Loading branch information
rmaucher committed Jan 2, 2024
1 parent ed8cc4f commit 705e364
Show file tree
Hide file tree
Showing 4 changed files with 646 additions and 520 deletions.
36 changes: 15 additions & 21 deletions java/org/apache/tomcat/util/net/openssl/panama/OpenSSLContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,8 @@
import org.apache.tomcat.util.net.openssl.OpenSSLConfCmd;
import org.apache.tomcat.util.net.openssl.OpenSSLStatus;
import org.apache.tomcat.util.net.openssl.OpenSSLUtil;
import org.apache.tomcat.util.openssl.PEM_read_bio_PrivateKey$cb;
import org.apache.tomcat.util.openssl.PEM_read_bio_X509_AUX$cb;
import org.apache.tomcat.util.openssl.SSL_CTX_set_alpn_select_cb$cb;
import org.apache.tomcat.util.openssl.SSL_CTX_set_cert_verify_callback$cb;
import org.apache.tomcat.util.openssl.SSL_CTX_set_default_passwd_cb$cb;
Expand Down Expand Up @@ -133,9 +135,6 @@ public class OpenSSLContext implements org.apache.tomcat.util.net.SSLContext {

private boolean noOcspCheck = false;

// Password callback
private final MemorySegment openSSLCallbackPassword;

private static final ConcurrentHashMap<Long, ContextState> states = new ConcurrentHashMap<>();
private static ContextState getState(MemorySegment ctx) {
return states.get(Long.valueOf(ctx.address()));
Expand Down Expand Up @@ -279,8 +278,8 @@ public OpenSSLContext(SSLHostConfigCertificate certificate, List<String> negotia
// Probably not needed

// Set int pem_password_cb(char *buf, int size, int rwflag, void *u) callback
openSSLCallbackPassword = SSL_CTX_set_default_passwd_cb$cb.allocate(new PasswordCallback(), contextArena);
SSL_CTX_set_default_passwd_cb(sslCtx, openSSLCallbackPassword);
SSL_CTX_set_default_passwd_cb(sslCtx,
SSL_CTX_set_default_passwd_cb$cb.allocate(new PasswordCallback(null), contextArena));

if (negotiableProtocols != null && negotiableProtocols.size() > 0) {
alpn = true;
Expand Down Expand Up @@ -891,15 +890,16 @@ private static String getCipherAuthenticationMethod(int auth, int kx) {
}
}

private static ThreadLocal<String> callbackPasswordTheadLocal = new ThreadLocal<>();

private static class PasswordCallback implements SSL_CTX_set_default_passwd_cb$cb {
private static class PasswordCallback implements SSL_CTX_set_default_passwd_cb$cb, PEM_read_bio_X509_AUX$cb, PEM_read_bio_PrivateKey$cb {
private final String callbackPassword;
PasswordCallback(String callbackPassword) {
this.callbackPassword = callbackPassword;
}
@Override
public int apply(MemorySegment /* char **/ buf, int bufsiz, int verify, MemorySegment /* void **/ cb) {
if (log.isDebugEnabled()) {
log.debug("Return password for certificate");
}
String callbackPassword = callbackPasswordTheadLocal.get();
if (callbackPassword != null && callbackPassword.length() > 0) {
try (var localArena = Arena.ofConfined()) {
MemorySegment callbackPasswordNative = localArena.allocateFrom(callbackPassword);
Expand Down Expand Up @@ -1020,12 +1020,9 @@ private boolean addCertificate(SSLHostConfigCertificate certificate, Arena local
}
key = MemorySegment.NULL;
for (int i = 0; i < 3; i++) {
try {
callbackPasswordTheadLocal.set(keyPassToUse);
key = PEM_read_bio_PrivateKey(keyBIO, MemorySegment.NULL, openSSLCallbackPassword, MemorySegment.NULL);
} finally {
callbackPasswordTheadLocal.set(null);
}
key = PEM_read_bio_PrivateKey(keyBIO, MemorySegment.NULL,
PEM_read_bio_PrivateKey$cb.allocate(new PasswordCallback(keyPassToUse), contextArena),
MemorySegment.NULL);
if (!MemorySegment.NULL.equals(key)) {
break;
}
Expand All @@ -1048,12 +1045,9 @@ private boolean addCertificate(SSLHostConfigCertificate certificate, Arena local
return false;
}
// Load certificate
try {
callbackPasswordTheadLocal.set(keyPassToUse);
cert = PEM_read_bio_X509_AUX(certificateBIO, MemorySegment.NULL, openSSLCallbackPassword, MemorySegment.NULL);
} finally {
callbackPasswordTheadLocal.set(null);
}
cert = PEM_read_bio_X509_AUX(certificateBIO, MemorySegment.NULL,
PEM_read_bio_X509_AUX$cb.allocate(new PasswordCallback(keyPassToUse), contextArena),
MemorySegment.NULL);
if (MemorySegment.NULL.equals(cert) &&
// Missing ERR_GET_REASON(ERR_peek_last_error())
/*int ERR_GET_REASON(unsigned long errcode) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

// Generated by jextract

package org.apache.tomcat.util.openssl;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.nio.ByteOrder;
import java.lang.foreign.*;
import static java.lang.foreign.ValueLayout.*;

/**
* {@snippet lang=c :
* int (*PEM_read_bio_PrivateKey$cb)(char* buf,int size,int rwflag,void* userdata);
* }
*/
public interface PEM_read_bio_PrivateKey$cb {

int apply(MemorySegment buf, int size, int rwflag, MemorySegment userdata);

FunctionDescriptor $DESC = FunctionDescriptor.of(
openssl_h.C_INT,
openssl_h.C_POINTER,
openssl_h.C_INT,
openssl_h.C_INT,
openssl_h.C_POINTER
);

MethodHandle UP$MH = openssl_h.upcallHandle(PEM_read_bio_PrivateKey$cb.class, "apply", $DESC);

static MemorySegment allocate(PEM_read_bio_PrivateKey$cb fi, Arena scope) {
return Linker.nativeLinker().upcallStub(UP$MH.bindTo(fi), $DESC, scope);
}

MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC);

static PEM_read_bio_PrivateKey$cb ofAddress(MemorySegment addr, Arena arena) {
MemorySegment symbol = addr.reinterpret(arena, null);
return (MemorySegment _buf, int _size, int _rwflag, MemorySegment _userdata) -> {
try {
return (int) DOWN$MH.invokeExact(symbol, _buf, _size, _rwflag, _userdata);
} catch (Throwable ex$) {
throw new AssertionError("should not reach here", ex$);
}
};
}
}

65 changes: 65 additions & 0 deletions java/org/apache/tomcat/util/openssl/PEM_read_bio_X509_AUX$cb.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

// Generated by jextract

package org.apache.tomcat.util.openssl;

import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.VarHandle;
import java.nio.ByteOrder;
import java.lang.foreign.*;
import static java.lang.foreign.ValueLayout.*;

/**
* {@snippet lang=c :
* int (*PEM_read_bio_X509_AUX$cb)(char* buf,int size,int rwflag,void* userdata);
* }
*/
public interface PEM_read_bio_X509_AUX$cb {

int apply(MemorySegment buf, int size, int rwflag, MemorySegment userdata);

FunctionDescriptor $DESC = FunctionDescriptor.of(
openssl_h.C_INT,
openssl_h.C_POINTER,
openssl_h.C_INT,
openssl_h.C_INT,
openssl_h.C_POINTER
);

MethodHandle UP$MH = openssl_h.upcallHandle(PEM_read_bio_X509_AUX$cb.class, "apply", $DESC);

static MemorySegment allocate(PEM_read_bio_X509_AUX$cb fi, Arena scope) {
return Linker.nativeLinker().upcallStub(UP$MH.bindTo(fi), $DESC, scope);
}

MethodHandle DOWN$MH = Linker.nativeLinker().downcallHandle($DESC);

static PEM_read_bio_X509_AUX$cb ofAddress(MemorySegment addr, Arena arena) {
MemorySegment symbol = addr.reinterpret(arena, null);
return (MemorySegment _buf, int _size, int _rwflag, MemorySegment _userdata) -> {
try {
return (int) DOWN$MH.invokeExact(symbol, _buf, _size, _rwflag, _userdata);
} catch (Throwable ex$) {
throw new AssertionError("should not reach here", ex$);
}
};
}
}

Loading

0 comments on commit 705e364

Please sign in to comment.