Example #1
0
int SslSocket::getError() const
{
    int       result;
    socklen_t rSize = sizeof (result);

    if (::getsockopt(impl->fd, SOL_SOCKET, SO_ERROR, &result, &rSize) < 0)
        throw QPID_POSIX_ERROR(errno);

    return result;
}
Example #2
0
SslSocket* SslSocket::accept() const
{
    int afd = ::accept(impl->fd, 0, 0);
    if ( afd >= 0) {
        return new SslSocket(new IOHandlePrivate(afd), prototype);
    } else if (errno == EAGAIN) {
        return 0;
    } else { 
        throw QPID_POSIX_ERROR(errno);
    }
}
Example #3
0
Socket* SslSocket::accept() const
{
    QPID_LOG(trace, "Accepting SSL connection.");
    int afd = ::accept(fd, 0, 0);
    if ( afd >= 0) {
        return new SslSocket(afd, prototype);
    } else if (errno == EAGAIN) {
        return 0;
    } else {
        throw QPID_POSIX_ERROR(errno);
    }
}
Example #4
0
Socket* SslMuxSocket::accept() const
{
    int afd = ::accept(fd, 0, 0);
    if (afd >= 0) {
        QPID_LOG(trace, "Accepting connection with optional SSL wrapper.");
        if (isSslStream(afd)) {
            QPID_LOG(trace, "Accepted SSL connection.");
            return new SslSocket(afd, prototype);
        } else {
            QPID_LOG(trace, "Accepted Plaintext connection.");
            return new BSDSocket(afd);
        }
    } else if (errno == EAGAIN) {
        return 0;
    } else {
        throw QPID_POSIX_ERROR(errno);
    }
}
Example #5
0
int SslSocket::listen(uint16_t port, int backlog, const std::string& certName, bool clientAuth) const
{
    //configure prototype socket:
    prototype = SSL_ImportFD(0, PR_NewTCPSocket());
    if (clientAuth) {
        NSS_CHECK(SSL_OptionSet(prototype, SSL_REQUEST_CERTIFICATE, PR_TRUE));
        NSS_CHECK(SSL_OptionSet(prototype, SSL_REQUIRE_CERTIFICATE, PR_TRUE));
    }

    //get certificate and key (is this the correct way?)
    CERTCertificate *cert = PK11_FindCertFromNickname(const_cast<char*>(certName.c_str()), 0);
    if (!cert) throw Exception(QPID_MSG("Failed to load certificate '" << certName << "'"));
    SECKEYPrivateKey *key = PK11_FindKeyByAnyCert(cert, 0);
    if (!key) throw Exception(QPID_MSG("Failed to retrieve private key from certificate"));
    NSS_CHECK(SSL_ConfigSecureServer(prototype, cert, key, NSS_FindCertKEAType(cert)));
    SECKEY_DestroyPrivateKey(key);
    CERT_DestroyCertificate(cert);

    //bind and listen
    const int& socket = impl->fd;
    int yes=1;
    QPID_POSIX_CHECK(setsockopt(socket,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)));
    struct sockaddr_in name;
    name.sin_family = AF_INET;
    name.sin_port = htons(port);
    name.sin_addr.s_addr = 0;
    if (::bind(socket, (struct sockaddr*)&name, sizeof(name)) < 0)
        throw Exception(QPID_MSG("Can't bind to port " << port << ": " << strError(errno)));
    if (::listen(socket, backlog) < 0)
        throw Exception(QPID_MSG("Can't listen on port " << port << ": " << strError(errno)));
    
    socklen_t namelen = sizeof(name);
    if (::getsockname(socket, (struct sockaddr*)&name, &namelen) < 0)
        throw QPID_POSIX_ERROR(errno);

    return ntohs(name.sin_port);
}
Example #6
0
static bool isSslStream(int afd) {
    int retries = SSL_STREAM_MAX_RETRIES;
    unsigned char buf[5] = {};

    do {
        struct pollfd fd = {afd, POLLIN, 0};

        /*
         * Note that this is blocking the accept thread, so connections that
         * send no data can limit the rate at which we can accept new
         * connections.
         */
        if (::poll(&fd, 1, SSL_STREAM_MAX_WAIT_ms) > 0) {
            errno = 0;
            int result = recv(afd, buf, sizeof(buf), MSG_PEEK | MSG_DONTWAIT);
            if (result == sizeof(buf)) {
                break;
            }
            if (errno && errno != EAGAIN) {
                int err = errno;
                ::close(afd);
                throw QPID_POSIX_ERROR(err);
            }
        }
    } while (retries-- > 0);

    if (retries < 0) {
        return false;
    }

    /*
     * SSLv2 Client Hello format
     * http://www.mozilla.org/projects/security/pki/nss/ssl/draft02.html
     *
     * Bytes 0-1: RECORD-LENGTH
     * Byte    2: MSG-CLIENT-HELLO (1)
     * Byte    3: CLIENT-VERSION-MSB
     * Byte    4: CLIENT-VERSION-LSB
     *
     * Allowed versions:
     * 2.0 - SSLv2
     * 3.0 - SSLv3
     * 3.1 - TLS 1.0
     * 3.2 - TLS 1.1
     * 3.3 - TLS 1.2
     *
     * The version sent in the Client-Hello is the latest version supported by
     * the client. NSS may send version 3.x in an SSLv2 header for
     * maximum compatibility.
     */
    bool isSSL2Handshake = buf[2] == 1 &&   // MSG-CLIENT-HELLO
                           ((buf[3] == 3 && buf[4] <= 3) ||    // SSL 3.0 & TLS 1.0-1.2 (v3.1-3.3)
                            (buf[3] == 2 && buf[4] == 0));     // SSL 2

    /*
     * SSLv3/TLS Client Hello format
     * RFC 2246
     *
     * Byte    0: ContentType (handshake - 22)
     * Bytes 1-2: ProtocolVersion {major, minor}
     *
     * Allowed versions:
     * 3.0 - SSLv3
     * 3.1 - TLS 1.0
     * 3.2 - TLS 1.1
     * 3.3 - TLS 1.2
     */
    bool isSSL3Handshake = buf[0] == 22 &&  // handshake
                           (buf[1] == 3 && buf[2] <= 3);       // SSL 3.0 & TLS 1.0-1.2 (v3.1-3.3)

    return isSSL2Handshake || isSSL3Handshake;
}
Example #7
0
SslSocket::SslSocket() : IOHandle(new IOHandlePrivate()), socket(0), prototype(0) 
{ 
    impl->fd = ::socket (PF_INET, SOCK_STREAM, 0);
    if (impl->fd < 0) throw QPID_POSIX_ERROR(errno);
    socket = SSL_ImportFD(0, PR_ImportTCPSocket(impl->fd));
}