Buy commercial curl support from WolfSSL. We help you work out your issues, debug your libcurl applications, use the API, port to new platforms, add new features and more. With a team lead by the curl founder himself.

Return

From: Pēteris Caune via curl-and-python <curl-and-python_at_lists.haxx.se>
Date: Thu, 02 Feb 2023 11:55:09 +0200

Hello,

I'm using pycurl and the OPENSOCKETFUNCTION callback to reject requests to private IP addresses:

    def _opensocket(purpose, curl_address):
        family, socktype, protocol, address = curl_address
        if not settings.INTEGRATIONS_ALLOW_PRIVATE_IPS:
            if ipaddress.ip_address(address[0]).is_private:
                return pycurl.SOCKET_BAD

        return socket.socket(family, socktype, protocol)

My client code catches pycurl.error exceptions, checks their error codes and generates appropriate error messages:

    try:
        c.perform()
    except pycurl.error as e:
        errcode = e.args[0]
        if errcode == pycurl.E_OPERATION_TIMEDOUT:
            raise CurlError("Connection timed out")
        elif errcode == pycurl.E_COULDNT_CONNECT:
            raise CurlError("Connection failed")
        ...

It looks like E_COULDNT_CONNECT can be returned for a variety of reasons. I'd like to give the user a specific error message if the request was blocked because of the private IP check: "Connection to a private IP such-and-such was refused" or something along these lines. So my _opensocket function would need to somehow smuggle out information about the failure reason. But I'm not sure what would be a safe way to do this. Would using a closure be fine?

    def _make_opensocket(errors):
        def _opensocket(purpose, curl_address):
            family, socktype, protocol, address = curl_address
            if not settings.INTEGRATIONS_ALLOW_PRIVATE_IPS:
                if ipaddress.ip_address(address[0]).is_private:
                    errors.append("more specific error code or errror message here")
                    return pycurl.SOCKET_BAD

            return socket.socket(family, socktype, protocol)

        return _opensocket

The caller would do:

    opensocket_errors = []
    c.setopt(pycurl.OPENSOCKETFUNCTION, _make_opensocket(opensocket_errors))

Or is there perhaps a more straightforward way to do the same?
I'll appreciate any tips,

Thanks,
Pēteris


-- 
curl-and-python mailing list
curl-and-python_at_lists.haxx.se
https://lists.haxx.se/listinfo/curl-and-python
Received on 2023-02-02