/* Copyright 2001-2005 The Apache Software Foundation or its licensors, as
 * applicable.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*                      _             _
 *  _ __ ___   ___   __| |    ___ ___| |  mod_ssl
 * | '_ ` _ \ / _ \ / _` |   / __/ __| |  Apache Interface to OpenSSL
 * | | | | | | (_) | (_| |   \__ \__ \ |
 * |_| |_| |_|\___/ \__,_|___|___/___/_|
 *                      |_____|
 *  ssl_scache_dbm.c
 *  Session Cache via DBM
 */

#include "ssl_private.h"

static void ssl_scache_dbm_expire(server_rec *s);

void ssl_scache_dbm_init(server_rec *s, apr_pool_t *p)
{
    SSLModConfigRec *mc = myModConfig(s);
    apr_dbm_t *dbm;
    apr_status_t rv;

    /* for the DBM we need the data file */
    if (mc->szSessionCacheDataFile == NULL) {
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
                     "SSLSessionCache required");
        ssl_die();
    }

    /* open it once to create it and to make sure it _can_ be created */
    ssl_mutex_on(s);
    if ((rv = apr_dbm_open(&dbm, mc->szSessionCacheDataFile,
            APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, mc->pPool)) != APR_SUCCESS) {
        ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
                     "Cannot create SSLSessionCache DBM file `%s'",
                     mc->szSessionCacheDataFile);
        ssl_mutex_off(s);
        return;
    }
    apr_dbm_close(dbm);

#if !defined(OS2) && !defined(WIN32) && !defined(BEOS) && !defined(NETWARE)
    /*
     * We have to make sure the Apache child processes have access to
     * the DBM file. But because there are brain-dead platforms where we
     * cannot exactly determine the suffixes we try all possibilities.
     */
    if (geteuid() == 0 /* is superuser */) {
        chown(mc->szSessionCacheDataFile, unixd_config.user_id, -1 /* no gid change */);
        if (chown(apr_pstrcat(p, mc->szSessionCacheDataFile, SSL_DBM_FILE_SUFFIX_DIR, NULL),
                  unixd_config.user_id, -1) == -1) {
            if (chown(apr_pstrcat(p, mc->szSessionCacheDataFile, ".db", NULL),
                      unixd_config.user_id, -1) == -1)
                chown(apr_pstrcat(p, mc->szSessionCacheDataFile, ".dir", NULL),
                      unixd_config.user_id, -1);
        }
        if (chown(apr_pstrcat(p, mc->szSessionCacheDataFile, SSL_DBM_FILE_SUFFIX_PAG, NULL),
                  unixd_config.user_id, -1) == -1) {
            if (chown(apr_pstrcat(p, mc->szSessionCacheDataFile, ".db", NULL),
                      unixd_config.user_id, -1) == -1)
                chown(apr_pstrcat(p, mc->szSessionCacheDataFile, ".pag", NULL),
                      unixd_config.user_id, -1);
        }
    }
#endif
    ssl_mutex_off(s);
    ssl_scache_dbm_expire(s);
    return;
}

void ssl_scache_dbm_kill(server_rec *s)
{
    SSLModConfigRec *mc = myModConfig(s);
    apr_pool_t *p;

    apr_pool_create_ex(&p, mc->pPool, NULL, NULL);
    if (p != NULL) {
        /* the correct way */
        unlink(apr_pstrcat(p, mc->szSessionCacheDataFile, SSL_DBM_FILE_SUFFIX_DIR, NULL));
        unlink(apr_pstrcat(p, mc->szSessionCacheDataFile, SSL_DBM_FILE_SUFFIX_PAG, NULL));
        /* the additional ways to be sure */
        unlink(apr_pstrcat(p, mc->szSessionCacheDataFile, ".dir", NULL));
        unlink(apr_pstrcat(p, mc->szSessionCacheDataFile, ".pag", NULL));
        unlink(apr_pstrcat(p, mc->szSessionCacheDataFile, ".db", NULL));
        unlink(mc->szSessionCacheDataFile);
        apr_pool_destroy(p);
    }
    return;
}

BOOL ssl_scache_dbm_store(server_rec *s, UCHAR *id, int idlen, time_t expiry, SSL_SESSION *sess)
{
    SSLModConfigRec *mc = myModConfig(s);
    apr_dbm_t *dbm;
    apr_datum_t dbmkey;
    apr_datum_t dbmval;
    UCHAR ucaData[SSL_SESSION_MAX_DER];
    int nData;
    UCHAR *ucp;
    apr_status_t rv;

    /* streamline session data */
    if ((nData = i2d_SSL_SESSION(sess, NULL)) > sizeof(ucaData)) {
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                     "streamline session data size too large: %d > "
                     "%" APR_SIZE_T_FMT,
                     nData, sizeof(ucaData));
        return FALSE;
    }
    ucp = ucaData;
    i2d_SSL_SESSION(sess, &ucp);

    /* be careful: do not try to store too much bytes in a DBM file! */
#ifdef PAIRMAX
    if ((idlen + nData) >= PAIRMAX) {
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                 "data size too large for DBM session cache: %d >= %d",
                 (idlen + nData), PAIRMAX);
        return FALSE;
    }
#else
    if ((idlen + nData) >= 950 /* at least less than approx. 1KB */) {
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                 "data size too large for DBM session cache: %d >= %d",
                 (idlen + nData), 950);
        return FALSE;
    }
#endif

    /* create DBM key */
    dbmkey.dptr  = (char *)id;
    dbmkey.dsize = idlen;

    /* create DBM value */
    dbmval.dsize = sizeof(time_t) + nData;
    dbmval.dptr  = (char *)malloc(dbmval.dsize);
    if (dbmval.dptr == NULL) {
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                 "malloc error creating DBM value");
        return FALSE;
    }
    memcpy((char *)dbmval.dptr, &expiry, sizeof(time_t));
    memcpy((char *)dbmval.dptr+sizeof(time_t), ucaData, nData);

    /* and store it to the DBM file */
    ssl_mutex_on(s);
    if ((rv = apr_dbm_open(&dbm, mc->szSessionCacheDataFile,
            APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, mc->pPool)) != APR_SUCCESS) {
        ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
                     "Cannot open SSLSessionCache DBM file `%s' for writing "
                     "(store)",
                     mc->szSessionCacheDataFile);
        ssl_mutex_off(s);
        free(dbmval.dptr);
        return FALSE;
    }
    if ((rv = apr_dbm_store(dbm, dbmkey, dbmval)) != APR_SUCCESS) {
        ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
                     "Cannot store SSL session to DBM file `%s'",
                     mc->szSessionCacheDataFile);
        apr_dbm_close(dbm);
        ssl_mutex_off(s);
        free(dbmval.dptr);
        return FALSE;
    }
    apr_dbm_close(dbm);
    ssl_mutex_off(s);

    /* free temporary buffers */
    free(dbmval.dptr);

    /* allow the regular expiring to occur */
    ssl_scache_dbm_expire(s);

    return TRUE;
}

SSL_SESSION *ssl_scache_dbm_retrieve(server_rec *s, UCHAR *id, int idlen)
{
    SSLModConfigRec *mc = myModConfig(s);
    apr_dbm_t *dbm;
    apr_datum_t dbmkey;
    apr_datum_t dbmval;
    SSL_SESSION *sess = NULL;
    MODSSL_D2I_SSL_SESSION_CONST unsigned char *ucpData;
    int nData;
    time_t expiry;
    time_t now;
    apr_status_t rc;

    /* allow the regular expiring to occur */
    ssl_scache_dbm_expire(s);

    /* create DBM key and values */
    dbmkey.dptr  = (char *)id;
    dbmkey.dsize = idlen;

    /* and fetch it from the DBM file
     * XXX: Should we open the dbm against r->pool so the cleanup will
     * do the apr_dbm_close? This would make the code a bit cleaner.
     */
    ssl_mutex_on(s);
    if ((rc = apr_dbm_open(&dbm, mc->szSessionCacheDataFile,
            APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, mc->pPool)) != APR_SUCCESS) {
        ap_log_error(APLOG_MARK, APLOG_ERR, rc, s,
                     "Cannot open SSLSessionCache DBM file `%s' for reading "
                     "(fetch)",
                     mc->szSessionCacheDataFile);
        ssl_mutex_off(s);
        return NULL;
    }
    rc = apr_dbm_fetch(dbm, dbmkey, &dbmval);
    if (rc != APR_SUCCESS) {
        apr_dbm_close(dbm);
        ssl_mutex_off(s);
        return NULL;
    }
    if (dbmval.dptr == NULL || dbmval.dsize <= sizeof(time_t)) {
        apr_dbm_close(dbm);
        ssl_mutex_off(s);
        return NULL;
    }

    /* parse resulting data */
    nData = dbmval.dsize-sizeof(time_t);
    ucpData = malloc(nData);
    if (ucpData == NULL) {
        apr_dbm_close(dbm);
        ssl_mutex_off(s);
        return NULL;
    }
    /* Cast needed, ucpData may be const */
    memcpy((unsigned char *)ucpData,
           (char *)dbmval.dptr + sizeof(time_t), nData);
    memcpy(&expiry, dbmval.dptr, sizeof(time_t));

    apr_dbm_close(dbm);
    ssl_mutex_off(s);

    /* make sure the stuff is still not expired */
    now = time(NULL);
    if (expiry <= now) {
        ssl_scache_dbm_remove(s, id, idlen);
        return NULL;
    }

    /* unstreamed SSL_SESSION */
    sess = d2i_SSL_SESSION(NULL, &ucpData, nData);

    return sess;
}

void ssl_scache_dbm_remove(server_rec *s, UCHAR *id, int idlen)
{
    SSLModConfigRec *mc = myModConfig(s);
    apr_dbm_t *dbm;
    apr_datum_t dbmkey;
    apr_status_t rv;

    /* create DBM key and values */
    dbmkey.dptr  = (char *)id;
    dbmkey.dsize = idlen;

    /* and delete it from the DBM file */
    ssl_mutex_on(s);
    if ((rv = apr_dbm_open(&dbm, mc->szSessionCacheDataFile,
            APR_DBM_RWCREATE, SSL_DBM_FILE_MODE, mc->pPool)) != APR_SUCCESS) {
        ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
                     "Cannot open SSLSessionCache DBM file `%s' for writing "
                     "(delete)",
                     mc->szSessionCacheDataFile);
        ssl_mutex_off(s);
        return;
    }
    apr_dbm_delete(dbm, dbmkey);
    apr_dbm_close(dbm);
    ssl_mutex_off(s);

    return;
}

static void ssl_scache_dbm_expire(server_rec *s)
{
    SSLModConfigRec *mc = myModConfig(s);
    SSLSrvConfigRec *sc = mySrvConfig(s);
    static time_t tLast = 0;
    apr_dbm_t *dbm;
    apr_datum_t dbmkey;
    apr_datum_t dbmval;
    apr_pool_t *p;
    time_t tExpiresAt;
    int nElements = 0;
    int nDeleted = 0;
    int bDelete;
    apr_datum_t *keylist;
    int keyidx;
    int i;
    time_t tNow;
    apr_status_t rv;

    /*
     * make sure the expiration for still not-accessed session
     * cache entries is done only from time to time
     */
    tNow = time(NULL);
    if (tNow < tLast+sc->session_cache_timeout)
        return;
    tLast = tNow;

    /*
     * Here we have to be very carefully: Not all DBM libraries are
     * smart enough to allow one to iterate over the elements and at the
     * same time delete expired ones. Some of them get totally crazy
     * while others have no problems. So we have to do it the slower but
     * more safe way: we first iterate over all elements and remember
     * those which have to be expired. Then in a second pass we delete
     * all those expired elements. Additionally we reopen the DBM file
     * to be really safe in state.
     */

#define KEYMAX 1024

    ssl_mutex_on(s);
    for (;;) {
        /* allocate the key array in a memory sub pool */
        apr_pool_create_ex(&p, mc->pPool, NULL, NULL);
        if (p == NULL)
            break;
        if ((keylist = apr_palloc(p, sizeof(dbmkey)*KEYMAX)) == NULL) {
            apr_pool_destroy(p);
            break;
        }

        /* pass 1: scan DBM database */
        keyidx = 0;
        if ((rv = apr_dbm_open(&dbm, mc->szSessionCacheDataFile,
                               APR_DBM_RWCREATE,SSL_DBM_FILE_MODE,
                               p)) != APR_SUCCESS) {
            ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
                         "Cannot open SSLSessionCache DBM file `%s' for "
                         "scanning",
                         mc->szSessionCacheDataFile);
            apr_pool_destroy(p);
            break;
        }
        apr_dbm_firstkey(dbm, &dbmkey);
        while (dbmkey.dptr != NULL) {
            nElements++;
            bDelete = FALSE;
            apr_dbm_fetch(dbm, dbmkey, &dbmval);
            if (dbmval.dsize <= sizeof(time_t) || dbmval.dptr == NULL)
                bDelete = TRUE;
            else {
                memcpy(&tExpiresAt, dbmval.dptr, sizeof(time_t));
                if (tExpiresAt <= tNow)
                    bDelete = TRUE;
            }
            if (bDelete) {
                if ((keylist[keyidx].dptr = apr_palloc(p, dbmkey.dsize)) != NULL) {
                    memcpy(keylist[keyidx].dptr, dbmkey.dptr, dbmkey.dsize);
                    keylist[keyidx].dsize = dbmkey.dsize;
                    keyidx++;
                    if (keyidx == KEYMAX)
                        break;
                }
            }
            apr_dbm_nextkey(dbm, &dbmkey);
        }
        apr_dbm_close(dbm);

        /* pass 2: delete expired elements */
        if (apr_dbm_open(&dbm, mc->szSessionCacheDataFile,
                APR_DBM_RWCREATE,SSL_DBM_FILE_MODE, p) != APR_SUCCESS) {
            ap_log_error(APLOG_MARK, APLOG_ERR, rv, s,
                         "Cannot re-open SSLSessionCache DBM file `%s' for "
                         "expiring",
                         mc->szSessionCacheDataFile);
            apr_pool_destroy(p);
            break;
        }
        for (i = 0; i < keyidx; i++) {
            apr_dbm_delete(dbm, keylist[i]);
            nDeleted++;
        }
        apr_dbm_close(dbm);

        /* destroy temporary pool */
        apr_pool_destroy(p);

        if (keyidx < KEYMAX)
            break;
    }
    ssl_mutex_off(s);

    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                 "Inter-Process Session Cache (DBM) Expiry: "
                 "old: %d, new: %d, removed: %d",
                 nElements, nElements-nDeleted, nDeleted);
    return;
}

void ssl_scache_dbm_status(request_rec *r, int flags, apr_pool_t *p)
{
    SSLModConfigRec *mc = myModConfig(r->server);
    apr_dbm_t *dbm;
    apr_datum_t dbmkey;
    apr_datum_t dbmval;
    int nElem;
    int nSize;
    int nAverage;
    apr_status_t rv;

    nElem = 0;
    nSize = 0;
    ssl_mutex_on(r->server);
    /*
     * XXX - Check what pool is to be used - TBD
     */
    if ((rv = apr_dbm_open(&dbm, mc->szSessionCacheDataFile,
                               APR_DBM_RWCREATE, SSL_DBM_FILE_MODE,
                           mc->pPool)) != APR_SUCCESS) {
        ap_log_rerror(APLOG_MARK, APLOG_ERR, rv, r,
                     "Cannot open SSLSessionCache DBM file `%s' for status "
                     "retrival",
                     mc->szSessionCacheDataFile);
        ssl_mutex_off(r->server);
        return;
    }
    /*
     * XXX - Check the return value of apr_dbm_firstkey, apr_dbm_fetch - TBD
     */
    apr_dbm_firstkey(dbm, &dbmkey);
    for ( ; dbmkey.dptr != NULL; apr_dbm_nextkey(dbm, &dbmkey)) {
        apr_dbm_fetch(dbm, dbmkey, &dbmval);
        if (dbmval.dptr == NULL)
            continue;
        nElem += 1;
        nSize += dbmval.dsize;
    }
    apr_dbm_close(dbm);
    ssl_mutex_off(r->server);
    if (nSize > 0 && nElem > 0)
        nAverage = nSize / nElem;
    else
        nAverage = 0;
    ap_rprintf(r, "cache type: <b>DBM</b>, maximum size: <b>unlimited</b><br>");
    ap_rprintf(r, "current sessions: <b>%d</b>, current size: <b>%d</b> bytes<br>", nElem, nSize);
    ap_rprintf(r, "average session size: <b>%d</b> bytes<br>", nAverage);
    return;
}

