示例#1
0
/* the SSL_read replacement routine which knows about the suck buffer */
static int ssl_io_suck_read(SSL *ssl, char *buf, int len)
{
    ap_ctx *actx;
    struct ssl_io_suck_st *ss;
    request_rec *r = NULL;
    int rv;

    actx = (ap_ctx *)SSL_get_app_data2(ssl);
    if (actx != NULL)
        r = (request_rec *)ap_ctx_get(actx, "ssl::request_rec");

    rv = -1;
    if (r != NULL && r->ctx != NULL) {
        ss = ap_ctx_get(r->ctx, "ssl::io::suck");
        if (ss != NULL) {
            if (ss->active && ss->pendlen > 0) {
                /* ok, there is pre-sucked data */
                len = (ss->pendlen > len ? len : ss->pendlen);
                memcpy(buf, ss->pendptr, len);
                ss->pendptr += len;
                ss->pendlen -= len;
                ssl_log(r->server, SSL_LOG_TRACE, 
                        "I/O: injecting %d bytes of pre-sucked data "
                        "into Apache I/O layer", len);
                rv = len;
            }
        }
    }
    if (rv == -1)
        rv = SSL_read(ssl, buf, len);
    return rv;
}
示例#2
0
static int SSL_recvwithtimeout(BUFF *fb, char *buf, int len)
{
    int iostate = 1;
    fd_set fdset;
    struct timeval tv;
    int err = WSAEWOULDBLOCK;
    int rv;
    int sock = fb->fd_in;
    SSL *ssl;
    int retry;

    ssl = ap_ctx_get(fb->ctx, "ssl");

    if (!(tv.tv_sec = ap_check_alarm()))
        return (SSL_read(ssl, buf, len));

    rv = ioctlsocket(sock, FIONBIO, &iostate);
    iostate = 0;
    ap_assert(!rv);
    rv = SSL_read(ssl, buf, len);
    if (rv <= 0) {
        if (BIO_sock_should_retry(rv)) {
            do {
                retry = 0;
                FD_ZERO(&fdset);
                FD_SET((unsigned int)sock, &fdset);
                tv.tv_usec = 0;
                rv = select(FD_SETSIZE, &fdset, NULL, NULL, &tv);
                if (rv == SOCKET_ERROR)
                    err = WSAGetLastError();
                else if (rv == 0) {
                    ioctlsocket(sock, FIONBIO, &iostate);
                    ap_check_alarm();
                    WSASetLastError(WSAEWOULDBLOCK);
                    return (SOCKET_ERROR);
                }
                else {
                    rv = SSL_read(ssl, buf, len);
                    if (rv == SOCKET_ERROR) {
                        if (BIO_sock_should_retry(rv)) {
                          ap_log_error(APLOG_MARK,APLOG_DEBUG, NULL,
                                       "select claimed we could read, "
                                       "but in fact we couldn't. "
                                       "This is a bug in Windows.");
                          retry = 1;
                          Sleep(100);
                        }
                        else {
                            err = WSAGetLastError();
                        }
                    }
                }
            } while(retry);
        }
    }
    ioctlsocket(sock, FIONBIO, &iostate);
    if (rv == SOCKET_ERROR)
        WSASetLastError(err);
    return (rv);
}
示例#3
0
static int ssl_io_hook_writev(BUFF *fb, const struct iovec *iov, int iovcnt)
{
    SSL *ssl;
    conn_rec *c;
    int rc;

    if ((ssl = ap_ctx_get(fb->ctx, "ssl")) != NULL) {
        rc = SSL_writev(ssl, iov, iovcnt);
        /*
         * Simulate an EINTR in case OpenSSL wants to write more.
         */
        if (rc < 0 && SSL_get_error(ssl, rc) == SSL_ERROR_WANT_WRITE)
            errno = EINTR;
        /*
         * Log SSL errors
         */
        if (rc < 0 && SSL_get_error(ssl, rc) == SSL_ERROR_SSL) {
            c = (conn_rec *)SSL_get_app_data(ssl);
            ssl_log(c->server, SSL_LOG_ERROR|SSL_ADD_SSLERR,
                    "SSL error on writing data");
        }
        /*
         * writev(2) returns only the generic error number -1
         */
        if (rc < 0)
            rc = -1;
    }
    else
        rc = writev(fb->fd, iov, iovcnt);
    return rc;
}
示例#4
0
static int ssl_io_hook_read(BUFF *fb, char *buf, int len)
{
    SSL *ssl;
    conn_rec *c;
    int rc;

    if ((ssl = ap_ctx_get(fb->ctx, "ssl")) != NULL) {
        rc = SSL_read(ssl, buf, len);
        /*
         * Simulate an EINTR in case OpenSSL wants to read more.
         * (This is usually the case when the client forces an SSL
         * renegotation which is handled implicitly by OpenSSL.)
         */
        if (rc < 0 && SSL_get_error(ssl, rc) == SSL_ERROR_WANT_READ)
            errno = EINTR;
        /*
         * Log SSL errors
         */
        if (rc < 0 && SSL_get_error(ssl, rc) == SSL_ERROR_SSL) {
            c = (conn_rec *)SSL_get_app_data(ssl);
            ssl_log(c->server, SSL_LOG_ERROR|SSL_ADD_SSLERR,
                    "SSL error on reading data");
        }
        /*
         * read(2) returns only the generic error number -1
         */
        if (rc < 0)
            rc = -1;
    }
    else
        rc = read(fb->fd_in, buf, len);
    return rc;
}
示例#5
0
/* record a sucked input chunk */
static void ssl_io_suck_record(request_rec *r, char *buf, int len)
{
    struct ssl_io_suck_st *ss;
    
    if ((ss = ap_ctx_get(r->ctx, "ssl::io::suck")) == NULL)
        return;
    if (((ss->bufptr + ss->buflen) - (ss->pendptr + ss->pendlen)) < len) {
        /* "expand" buffer: actually we cannot really expand the buffer
           here, because Apache's pool system doesn't support expanding chunks
           of memory. Instead we have to either reuse processed data or
           allocate a new chunk of memory in advance if we really need more
           memory. */
        int newlen;
        char *newptr;

        if ((  (ss->pendptr - ss->bufptr) 
             + ((ss->bufptr + ss->buflen) - (ss->pendptr + ss->pendlen)) ) >= len) {
            /* make memory available by reusing already processed data */
            memmove(ss->bufptr, ss->pendptr, ss->pendlen);
            ss->pendptr = ss->bufptr;
        }
        else {
            /* too bad, we have to allocate a new larger buffer */
            newlen = (ss->buflen * 2) + len;
            newptr = ap_palloc(r->pool, newlen);
            ss->bufptr  = newptr;
            ss->buflen  = newlen;
            memcpy(ss->bufptr, ss->pendptr, ss->pendlen);
            ss->pendptr = ss->bufptr;
        }
    }
    memcpy(ss->pendptr+ss->pendlen, buf, len);
    ss->pendlen += len;
    return;
}
示例#6
0
static int ssl_io_hook_sendwithtimeout(BUFF *fb, const char *buf, int len)
{
    SSL *ssl;
    int rc;

    if ((ssl = ap_ctx_get(fb->ctx, "ssl")) != NULL)
        rc = SSL_sendwithtimeout(fb, buf, len);
    else
        rc = ap_sendwithtimeout(fb->fd, buf, len, 0);
    return rc;
}
示例#7
0
/* finish request_rec after input sucking */
static void ssl_io_suck_end(request_rec *r)
{
    struct ssl_io_suck_st *ss;
    
    if ((ss = ap_ctx_get(r->ctx, "ssl::io::suck")) == NULL)
        return;
    ss->active = TRUE;
    r->read_body    = REQUEST_NO_BODY;
    r->read_length  = 0;
    r->read_chunked = 0;
    r->remaining    = 0;
    ap_bsetflag(r->connection->client, B_CHUNK, 0);
    return;
}
示例#8
0
void ssl_config_global_create(void)
{
    pool *pPool;
    SSLModConfigRec *mc;

    mc = ap_ctx_get(ap_global_ctx, "ssl_module");
    if (mc == NULL) {
        /*
         * allocate an own subpool which survives server restarts
         */
        pPool = ap_make_sub_pool(NULL);
        mc = (SSLModConfigRec *)ap_palloc(pPool, sizeof(SSLModConfigRec));
        mc->pPool = pPool;
        mc->bFixed = FALSE;

        /*
         * initialize per-module configuration
         */
        mc->nInitCount             = 0;
        mc->nSessionCacheMode      = SSL_SCMODE_UNSET;
        mc->szSessionCacheDataFile = NULL;
        mc->nSessionCacheDataSize  = 0;
        mc->pSessionCacheDataMM    = NULL;
        mc->tSessionCacheDataTable = NULL;
        mc->nMutexMode             = SSL_MUTEXMODE_UNSET;
        mc->szMutexFile            = NULL;
        mc->nMutexFD               = -1;
        mc->nMutexSEMID            = -1;
        mc->aRandSeed              = ap_make_array(pPool, 4, sizeof(ssl_randseed_t));
        mc->tPrivateKey            = ssl_ds_table_make(pPool, sizeof(ssl_asn1_t));
        mc->tPublicCert            = ssl_ds_table_make(pPool, sizeof(ssl_asn1_t));
        mc->tTmpKeys               = ssl_ds_table_make(pPool, sizeof(ssl_asn1_t));
#ifdef SSL_EXPERIMENTAL_ENGINE
        mc->szCryptoDevice         = NULL;
#endif

        (void)memset(mc->pTmpKeys, 0, SSL_TKPIDX_MAX*sizeof(void *));

#ifdef SSL_VENDOR
        mc->ctx = ap_ctx_new(pPool);
        ap_hook_use("ap::mod_ssl::vendor::config_global_create",
                AP_HOOK_SIG2(void,ptr), AP_HOOK_MODE_ALL, mc);
#endif

        /*
         * And push it into Apache's global context
         */
        ap_ctx_set(ap_global_ctx, "ssl_module", mc);
    }
示例#9
0
/* prepare request_rec structure for input sucking */
static void ssl_io_suck_start(request_rec *r)
{
    struct ssl_io_suck_st *ss;

    ss = ap_ctx_get(r->ctx, "ssl::io::suck");
    if (ss == NULL) {
        ss = ap_palloc(r->pool, sizeof(struct ssl_io_suck_st));
        ap_ctx_set(r->ctx, "ssl::io::suck", ss);
        ss->buflen  = 8192;
        ss->bufptr  = ap_palloc(r->pool, ss->buflen);
    }
    ss->pendptr = ss->bufptr;
    ss->pendlen = 0;
    ss->active = FALSE;
    return;
}