Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

loopback address connect and accept blocking in mac os platform #18

Open
superajun-wsj opened this issue Jun 2, 2023 · 0 comments
Open

Comments

@superajun-wsj
Copy link
Collaborator

test case test_SSLSocket_endpointIdentification_Failure and test_SSLSocket_reusedNpnSocket can pass in linux platform while fail in mac os platform. One demo could reproduce it:
`package com.example;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.lang.reflect.Method;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.security.NoSuchAlgorithmException;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLSocket;

public class Socket {
private static class HostnameRewritingObjectOutputStream extends ObjectOutputStream {
private final String hostname;

    public HostnameRewritingObjectOutputStream(OutputStream out, String hostname)
            throws IOException {
        super(out);
        this.hostname = hostname;
    }

    @Override
    public PutField putFields() throws IOException {
        return new PutFieldProxy(super.putFields(), hostname);
    }

    private static class PutFieldProxy extends ObjectOutputStream.PutField {
        private final PutField delegate;
        private final String hostname;

        public PutFieldProxy(ObjectOutputStream.PutField delegate, String hostname) {
            this.delegate = delegate;
            this.hostname = hostname;
        }

        @Override
        public void put(String name, boolean val) {
            delegate.put(name, val);
        }

        @Override
        public void put(String name, byte val) {
            delegate.put(name, val);
        }

        @Override
        public void put(String name, char val) {
            delegate.put(name, val);
        }

        @Override
        public void put(String name, short val) {
            delegate.put(name, val);
        }

        @Override
        public void put(String name, int val) {
            delegate.put(name, val);
        }

        @Override
        public void put(String name, long val) {
            delegate.put(name, val);
        }

        @Override
        public void put(String name, float val) {
            delegate.put(name, val);
        }

        @Override
        public void put(String name, double val) {
            delegate.put(name, val);
        }

        @Override
        public void put(String name, Object val) {
            if ("hostname".equals(name)) {
                delegate.put(name, hostname);
            } else {
                delegate.put(name, val);
            }
        }

        @SuppressWarnings("deprecation")
        @Override
        public void write(ObjectOutput out) throws IOException {
            delegate.write(out);
        }
    }
}

public static InetAddress getLoopbackAddress() {
    try {
        Method method = InetAddress.class.getMethod("getLoopbackAddress");
        return (InetAddress) method.invoke(null);
    } catch (Exception ignore) {
        // Ignored.
    }
    try {
        return InetAddress.getLocalHost();
    } catch (UnknownHostException e) {
        throw new RuntimeException(e);
    }
}

public static InetSocketAddress getLoopbackAsHostname(String hostname, int port)
        throws Exception {
    InetSocketAddress addr = new InetSocketAddress(getLoopbackAddress(), port);
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    HostnameRewritingObjectOutputStream oos = new HostnameRewritingObjectOutputStream(baos, hostname);
    oos.writeObject(addr);
    oos.close();
    ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(baos.toByteArray()));
    return (InetSocketAddress) ois.readObject();
}

public static void main(String[] args) throws Exception {
    SSLContext context = SSLContext.getDefault();
    SSLServerSocket server = (SSLServerSocket) context.getServerSocketFactory().createServerSocket();
    InetAddress host = getLoopbackAddress();
    server.bind(new InetSocketAddress(host, 0));
    int port = server.getLocalPort();

    SSLSocket client = (SSLSocket) context.getSocketFactory().createSocket();
    SSLParameters paras = client.getSSLParameters();
    paras.setEndpointIdentificationAlgorithm("HTTPS");
    client.setSSLParameters(paras);

    InetSocketAddress add = getLoopbackAsHostname("unmatched.example.com", port);
    client.connect(add);
    System.out.println("connect is finished");
    SSLSocket serverPipe = (SSLSocket) server.accept();
    System.out.println(serverPipe);
}

}`
this demo could pass in linux while not in mac os platform. it will be blocked in accept() for ever.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant