Example #1
0
std::streamsize Connection::read(char* buf, std::size_t n, std::streamsize maxImport)
{
    log_trace("Connection::read");

    std::streambuf* sb = _ios->rdbuf();
    if( ! sb)
        return 0;

    if(maxImport == 0) 
        maxImport = sb->in_avail();

    std::size_t processed = 0;
    
    _isReading = true;
    _maxImport = maxImport;
    OSStatus error = SSLRead(_context, buf, n, &processed);
    _isReading = false;

    log_trace("Connection::read: " << error);
    
    if(error == errSSLClosedGraceful)
    {
        _receivedShutdown = true;
    }
    else if(error != noErr && error != errSSLWouldBlock)
    {
        throw SslError("decoding failed");
    }

    return static_cast<std::streamsize>(processed);
}
Example #2
0
bool Connection::readHandshake()
{
    log_trace("Connection::readHandshake");

    std::streambuf* sb = _ios->rdbuf();
    if( ! sb)
        return true;

    while(_ios->rdbuf()->in_avail() > 0)
    {
        const std::streamsize bufsize = 2000;
        char buf[bufsize];

        std::streamsize gsize = std::min( sb->in_avail(), bufsize );
        std::streamsize n = sb->sgetn(buf, gsize);

        const int written = BIO_write(_in, buf, static_cast<int>(n));
        assert(written == n);

        if(written <= 0 || written != n)
            throw SslError("BIO_write");

        log_debug("read " << n << " bytes from input");
    }

    int ret = SSL_do_handshake(_ssl);
    log_debug("SSL_do_handshake returns " << ret);

    if( ret <= 0 )
    {
        int sslerr = SSL_get_error(_ssl, ret);
        if( sslerr != SSL_ERROR_WANT_READ && sslerr != SSL_ERROR_WANT_WRITE) 
        {
            if(sslerr == SSL_ERROR_SSL)
            {
                char buf[255];
                ERR_error_string_n(ERR_get_error(), buf, sizeof(buf));
                log_warn("handshake failed: " << buf);
            }

            throw HandshakeFailed("SSL handshake failed");
        }
    }

    if( ret == 1 && BIO_pending(_out) <= 0 )
    {
        _connected = true;
    }

    return BIO_pending(_out) <= 0 && SSL_want_read(_ssl);   
}
Example #3
0
int SslOcspStapling::certVerify(OCSP_RESPONSE *pResponse,
                                OCSP_BASICRESP *pBasicResp, X509_STORE *pXstore)
{
    int                 n, iResult = -1;
    STACK_OF(X509)      *pXchain;
    ASN1_GENERALIZEDTIME  *pThisupdate, *pNextupdate;
    struct stat         st;

    pXchain = m_pCtx->extra_certs;
    if (OCSP_basic_verify(pBasicResp, pXchain, pXstore, OCSP_NOVERIFY) == 1)
    {
        if ((m_pCertId != NULL)
            && (OCSP_resp_find_status(pBasicResp, m_pCertId, &n,
                                      NULL, NULL, &pThisupdate, &pNextupdate) == 1)
            && (n == V_OCSP_CERTSTATUS_GOOD)
            && (OCSP_check_validity(pThisupdate, pNextupdate, 300, -1) == 1))
        {
            iResult = 0;
            updateRespData(pResponse);
            unlink(m_sRespfile.c_str());
            rename(m_sRespfileTmp.c_str(), m_sRespfile.c_str());
            if (::stat(m_sRespfile.c_str(), &st) == 0)
                m_RespTime = st.st_mtime;
        }
    }
    else
        Logger::getRootLogger()->error("OCSP_basic_verify() failed: %s\n",
                                       SslError().what());
    if (iResult)
    {
        setLastErrMsg("%s", SslError().what());
        ERR_clear_error();
        if (m_pHttpFetch)
            m_pHttpFetch->writeLog(s_ErrMsg.c_str());

    }
    return iResult;
}
Example #4
0
std::streamsize Connection::write(const char* buf, std::size_t n)
{
    std::streambuf* sb = _ios->rdbuf();
    if( ! sb)
        return 0;

    std::size_t processed = 0;
    OSStatus error = SSLWrite(_context, buf, n, &processed);
    
    if(error != noErr && error != errSSLWouldBlock)
        throw SslError("encoding failed");

    return static_cast<std::streamsize>(processed);
}
Example #5
0
bool Connection::writeHandshake()
{
    log_trace("Connection::writeHandshake");

    std::streambuf* sb = _ios->rdbuf();
    if( ! sb)
        return false;

    int ret = SSL_do_handshake(_ssl);
    log_debug("SSL_do_handshake returns " << ret);

    if(ret <= 0)
    {
        const int sslerr = SSL_get_error(_ssl, ret);
        if(sslerr != SSL_ERROR_WANT_READ && sslerr != SSL_ERROR_WANT_WRITE) 
        {
            if(sslerr == SSL_ERROR_SSL)
            {
                char buf[255];
                ERR_error_string_n(ERR_get_error(), buf, sizeof(buf));
                log_warn("handshake failed: " << buf);
            }
            
            throw HandshakeFailed("SSL handshake failed");
        }
    }

    if(ret == 1)
    {
        _connected = true;
    }

    if( BIO_pending(_out) )
    {
        char buff[1000];
        const int n = BIO_read(_out, buff, sizeof(buff));
        log_debug("wrote " << n << " bytes to output");

        if(n <= 0)
            throw SslError("BIO_read");

        sb->sputn(buff, n);
        return true;
    }

    return SSL_want_write(_ssl);   
}
Example #6
0
int ProxyConn::connectSSL()
{
    if (!m_ssl.getSSL())
    {
        m_ssl.setSSL(getSslConn());
        if (!m_ssl.getSSL())
            return LS_FAIL;
        m_ssl.setfd(getfd());
        HttpReq *pReq = getConnector()->getHttpSession()->getReq();
        char *pHostName;
        int hostLen = pReq->getNewHostLen();
        if (hostLen > 0)
            pHostName = (char *)pReq->getNewHost();
        else
        {
            pHostName = (char *)pReq->getHeader(HttpHeader::H_HOST);
            hostLen = pReq->getHeaderLen(HttpHeader::H_HOST);
        }
        if (pHostName)
        {
            char ch = *(pHostName + hostLen);
            *(pHostName + hostLen) = 0;
            m_ssl.setTlsExtHostName(pHostName);
            *(pHostName + hostLen) = ch;
        }
    }
    int ret = m_ssl.connect();
    switch (ret)
    {
    case 0:
        setSSLAgain();
        break;
    case 1:
        LS_DBG_L(this, "[SSL] connected!");
        break;
    default:
        if (errno == EIO)
            LS_DBG_L(this, "SSL_connect() failed!: %s ", SslError().what());
        break;
    }

    return ret;
}
Example #7
0
std::streamsize Connection::read(char* buf, std::size_t n, std::streamsize maxImport)
{
    std::streambuf* sb = _ios->rdbuf();
    if( ! sb)
        return 0;

    if(maxImport == 0) 
        maxImport = sb->in_avail();

    while(true) 
    {
        // even if we could not refill the BIO, we might still get data from the SSL
        const int readSize = SSL_read(_ssl, buf, n);
        log_debug("Read " << readSize << " bytes from _ssl");
        log_debug("SSL_get_shutdown() = " << SSL_get_shutdown(_ssl));

        if(readSize > 0)
        {           
            return readSize;
        }

        long sslerr = SSL_get_error(_ssl, readSize);

        // happens when the peer has send the shutdown alert
        if(sslerr == SSL_ERROR_ZERO_RETURN)
        {
            log_debug("SSL_ERROR_ZERO_RETURN");
            return 0;
        }

        if(sslerr != SSL_ERROR_WANT_READ)
        {
            log_debug("ssl error occured");
            while( sslerr = ERR_get_error() ) 
            {
                log_debug("ERR_error_string = " << ERR_error_string(sslerr, 0));
            }
            
            throw SslError("SSL_read");
        }

        if(maxImport == 0)
            return 0;

        // Refill the BIO with encoded bytes for decoding
        BUF_MEM* bm = 0;
        BIO_get_mem_ptr(_in, &bm);

        if(bm->max == bm->length)
            continue;

        const std::streamsize refill = std::min(static_cast<std::streamsize>(bm->max - bm->length), maxImport);
        log_debug("get " << refill << " bytes from _ios");
        
        std::streamsize gcount = sb->sgetn(bm->data + bm->length, refill);
        if(gcount <= 0)
            return 0;

        bm->length += static_cast<int>( gcount );
        log_debug("Wrote " << gcount << " bytes from _ios to _in BUF_MEM");

        maxImport -= gcount;
    }

    return 0;
}
Example #8
0
bool Connection::shutdown()
{
    log_debug("Connection::shutdown");

    if( ! _connected )
        return true;

    std::streambuf* sb = _ios->rdbuf();
    if( ! sb)
        return false;

    int state = SSL_get_shutdown(_ssl);
    log_debug("SSL_get_shutdown() = " << state);

    bool shutdownSent = (SSL_SENT_SHUTDOWN & state) == SSL_SENT_SHUTDOWN;

    if( ! shutdownSent )
    {
        // write shutdown notify
        log_debug("write shutdown notify");

        int r = SSL_shutdown(_ssl);
        log_debug("SSL_shutdown() = " << r);

        char buf[1000];
        const int n = BIO_read(_out, buf, sizeof(buf));
        if(n <= 0)
            throw SslError("BIO_read");

        sb->sputn(buf, n);
        log_debug("wrote " << n << " bytes to output");

        if(r == 1)
        {
            log_debug("shutdown complete");
            SSL_clear(_ssl);
            _connected = false;
            return true;
        }
    }

    // read shutdown notify
    log_debug("read shutdown notify");

    BUF_MEM* bm = 0;
    BIO_get_mem_ptr(_in, &bm);

    std::streamsize avail = sb->in_avail();
    std::streamsize refill = std::min(static_cast<std::streamsize>(bm->max - bm->length), avail);
    log_debug("refill " << refill << " bytes");
        
    std::streamsize gcount = sb->sgetn(bm->data + bm->length, refill);
    bm->length += static_cast<int>( gcount );
    log_debug("got " << gcount << " bytes from input stream");

    int r = SSL_shutdown(_ssl);
    log_debug("SSL_shutdown() = " << r);

    if(r == 1)
    {
        log_debug("shutdown complete");
        SSL_clear(_ssl);
        _connected = false;
        return true;
    }

    return false;
}
Example #9
0
bool Connection::shutdown()
{
    if( ! _connected )
        return true;

    std::streambuf* sb = _ios->rdbuf();
    if( ! sb)
        return false;

    if( ! _sentShutdown)
    {
        // write shutdown notify
        log_debug("write shutdown notify");

        _isWriting = true;
        OSStatus error = SSLClose(_context);
        _isWriting = false;

        log_debug("SSLClose: " << error);

        if(error == errSSLWouldBlock)
        {
            // need to read shutdown alert
            log_debug("want to read shutdown alert");
            _sentShutdown = true;
            return false;
        }

        if(error != noErr)
            throw SslError("shutdown failed");

        log_debug("shutdown complete");
        _connected = false;
        _sentShutdown = false;
        _receivedShutdown = false;
        return true;
    }
    
    // read shutdown notify
    log_debug("read shutdown notify");

    _maxImport = sb->in_avail();
    _wantRead = false;
    _isReading = true;
    OSStatus error = SSLClose(_context);
    _isReading = false;

    log_debug("SSLClose: " << error);

    if(error == errSSLWouldBlock)
    {
        return false;
    }

    if(error != noErr)
        throw SslError("shutdown failed");

    log_debug("shutdown complete");
    _connected = false;
    _sentShutdown = false;
    _receivedShutdown = false;
    return true;
}