Skip to content
New issue

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

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

Already on GitHub? # 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.

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

No branches or pull requests

1 participant