Let the kernel choose the port (ephemeral port)

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Let the kernel choose the port (ephemeral port)

Robert Stober
Good Afternoon,

I solved one of my problems, and banged my head against the wall all day
trying to figure out how to get the OS to select a port for my
application. Every example I see shows the port being explicitly set,
whereas I need the OS to do this so that I can be sure the port is free.


I've determined that it just can't be done using BIO. So my plan is to
create the socket and then attach the BIO to it. Here's the short
version (the long version is below)::

     int       listenfd;
        struct    sockaddr_in server = {AF_INET, INADDR_ANY,
INADDR_ANY};

        init_OpenSSL();
        logInfo("Initialized OpenSSL library\n");

        seed_prng();

        ctx = setup_server_ctx();
          /*
           * THIS IS THE PART I CHANGED TO TRY AND GET AN EPHEMERAL PORT

         */

        if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
                log_error("Socket call failed\n");

        if (bind(listenfd, (struct sockaddr *)&server, SIZE) == -1)
                log_error("Bind call failed\n");

        acc = BIO_new_socket(listenfd, BIO_CLOSE);

          /*
         * THE ABOVE WAS WORKING WHEN I WAS USING acc =
BIO_new_accept(PORT);
         * BUT THEN I WAS ASSIGNING THE PORT MANUALLY.
         */

        if (!acc)
                log_error("Error creating server socket\n");
        else
                logInfo("Created server socket\n");

          /* This wasn't working, and why should it? I already binded
the socket above...
        if (BIO_do_accept(acc) <= 0)
                log_error("Error binding server socket\n");
        else
                logInfo("Binded server socket\n"); */

        portStr = BIO_get_accept_port(acc);
        logInfo("PortStr: %s\n", portStr);

        if (!(ssl = SSL_new(ctx)))
                log_error("Error creating SSL context\n");
        else
                logInfo("Created SSL context\n");

        SSL_set_bio(ssl, acc, acc);

        if (SSL_accept(ssl) <= 0)
                log_error("Error accepting SSL connection\n");
        else
                logInfo("Accepted SSL connection\n");


This compiles but when I run it I get "Error accepting SSL connection".
The eerror queue shows:

SSL_ERROR_SYSCALL - which is what I get when the server is not running!

Any pointers at all would be immensely helpful as I've found next to
nothing on setting up an ephemeral port using SSL /BIO. I just want the
OS to select an available ephemeral port for me.

Thank you,

Robert


PS: Here's the full function for anyone who needs to see more of the
code:

vauth(char *host)
{

        char *eauth_client, *eauth_server;
    char *aux_pass, *aux_file;
        eauth_client = getenv("LSF_EAUTH_CLIENT");
    eauth_server = getenv("LSF_EAUTH_SERVER");
    aux_pass = getenv("LSF_EAUTH_AUX_PASS");
    aux_file = getenv("LSF_EAUTH_AUX_DATA");

        logInfo( "=================== eauth -c
========================\n");
    logInfo( "eauth -c called for host %s\n", host);
    logInfo( "CLIENT == %s, SERVER == %s, AUX_PASS == %s, AUX_FILE ==
%s\n",
        eauth_client ? eauth_client : "NULL",
        eauth_server ? eauth_server : "NULL",
        aux_pass ? aux_pass : "NULL",
                aux_file ? aux_file : "NULL");
    logInfo( "USER == %s\n", getenv("USER") ? getenv("USER") : "none");

        BIO                     *acc;
        SSL                     *ssl;
        SSL_CTX         *ctx;
        long            lngErr;
        int             fd;
        char            *portStr;
        int             listenfd;
        struct          sockaddr_in server = {AF_INET, INADDR_ANY,
INADDR_ANY};

        init_OpenSSL();
        logInfo("Initialized OpenSSL library\n");

        seed_prng();

        ctx = setup_server_ctx();

        if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
                log_error("Socket call failed\n");

        if (bind(listenfd, (struct sockaddr *)&server, SIZE) == -1)
                log_error("Bind call failed\n");

        acc = BIO_new_socket(listenfd, BIO_CLOSE);
        /* acc = BIO_new_accept(PORT); */

        if (!acc)
                log_error("Error creating server socket\n");
        else
                logInfo("Created server socket\n");

        /* if (BIO_do_accept(acc) <= 0)
                log_error("Error binding server socket\n");
        else
                logInfo("Binded server socket\n"); */

        portStr = BIO_get_accept_port(acc);
        logInfo("PortStr: %s\n", portStr);

        if (!(ssl = SSL_new(ctx)))
                log_error("Error creating SSL context\n");
        else
                logInfo("Created SSL context\n");

        SSL_set_bio(ssl, acc, acc);

        if (SSL_accept(ssl) <= 0)
                log_error("Error accepting SSL connection\n");
        else
                logInfo("Accepted SSL connection\n");

    fd = BIO_get_fd(acc,&fd);
        logInfo("fd is: %d\n", fd);

        if ((lngErr = post_connection_check(ssl, CLIENT)) != X509_V_OK)
                log_error("Client certificate failed post-connection
checks: %s\n", X509_verify_cert_error_string(lngErr));
        else
                logInfo("Client certificate passed all post-connecton
checks\n");

        logInfo("SSL connection opened\n");

        if (do_server_loop(ssl))
                SSL_shutdown(ssl);
        else
                SSL_clear(ssl);

        logInfo("Connection closed\n");

        SSL_free(ssl);
        ERR_remove_state(0);
        SSL_CTX_free(ctx);
        BIO_free(acc);
        return 0;

} /* vauth */

-----Original Message-----
From: [hidden email]
[mailto:[hidden email]] On Behalf Of Robert Stober
Sent: Wednesday, April 12, 2006 9:56 AM
To: [hidden email]
Subject: BIO_new_accept: How to set ephemeral port and then get port
number?


Good Morning,

I'm currently creating a socket that can accept remote connections using
conn = BIO_new_accept(PORT) and then binding that port using
BIO_do_accept(conn).

But what I want is for the system to choose an ephemeral port for me,
and then I want to find out what that port number is.

1. If I pass the integer '0' into BIO_new_accept, will I get an
ephemeral port when I bind the connection? If not how can I do this?

2. Once I get an ephemeral port, how can I find out what port was
assigned?

Thank you,

Robert


Robert Stober
Senior Systems Engineer
Platform Computing, Inc.
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    [hidden email]
Automated List Manager                           [hidden email]
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    [hidden email]
Automated List Manager                           [hidden email]
Reply | Threaded
Open this post in threaded view
|

Re: Let the kernel choose the port (ephemeral port)

Dr. Stephen Henson
On Wed, Apr 12, 2006, Robert Stober wrote:

> Good Afternoon,
>
> I solved one of my problems, and banged my head against the wall all day
> trying to figure out how to get the OS to select a port for my
> application. Every example I see shows the port being explicitly set,
> whereas I need the OS to do this so that I can be sure the port is free.
>
>
> I've determined that it just can't be done using BIO. So my plan is to
> create the socket and then attach the BIO to it. Here's the short
> version (the long version is below)::
>
>      int       listenfd;
>         struct    sockaddr_in server = {AF_INET, INADDR_ANY,
> INADDR_ANY};
>
>         init_OpenSSL();
>         logInfo("Initialized OpenSSL library\n");
>
>         seed_prng();
>
>         ctx = setup_server_ctx();
>  /*
>   * THIS IS THE PART I CHANGED TO TRY AND GET AN EPHEMERAL PORT
>
>          */
>
>         if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
>                 log_error("Socket call failed\n");
>
>         if (bind(listenfd, (struct sockaddr *)&server, SIZE) == -1)
>                 log_error("Bind call failed\n");
>
>         acc = BIO_new_socket(listenfd, BIO_CLOSE);
>
>  /*
>          * THE ABOVE WAS WORKING WHEN I WAS USING acc =
> BIO_new_accept(PORT);
>          * BUT THEN I WAS ASSIGNING THE PORT MANUALLY.
>          */
>
>         if (!acc)
>                 log_error("Error creating server socket\n");
>         else
>                 logInfo("Created server socket\n");
>
>  /* This wasn't working, and why should it? I already binded
> the socket above...
>         if (BIO_do_accept(acc) <= 0)
>                 log_error("Error binding server socket\n");
>         else
>                 logInfo("Binded server socket\n"); */
>
>         portStr = BIO_get_accept_port(acc);
>         logInfo("PortStr: %s\n", portStr);
>
>         if (!(ssl = SSL_new(ctx)))
>                 log_error("Error creating SSL context\n");
>         else
>                 logInfo("Created SSL context\n");
>
>         SSL_set_bio(ssl, acc, acc);
>
>         if (SSL_accept(ssl) <= 0)
>                 log_error("Error accepting SSL connection\n");
>         else
>                 logInfo("Accepted SSL connection\n");
>
>
> This compiles but when I run it I get "Error accepting SSL connection".
> The eerror queue shows:
>
> SSL_ERROR_SYSCALL - which is what I get when the server is not running!
>
> Any pointers at all would be immensely helpful as I've found next to
> nothing on setting up an ephemeral port using SSL /BIO. I just want the
> OS to select an available ephemeral port for me.
>

I think the problem is that BIO_new_socket() is expecting a connected
socket. The calls to BIO_do_accept() only work for an accept BIO whereas you
have a socket BIO.

I'd suggest you use an accept BIO but set up the socket using the calls
similar to those above. Then call BIO_set_fd() on that accept BIO.

Steve.
--
Dr Stephen N. Henson. Email, S/MIME and PGP keys: see homepage
OpenSSL project core developer and freelance consultant.
Funding needed! Details on homepage.
Homepage: http://www.drh-consultancy.demon.co.uk
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    [hidden email]
Automated List Manager                           [hidden email]