Example #1
0
int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c) {
  int ret = 0;
  SSL_SESSION *s;

  /* add just 1 reference count for the SSL_CTX's session cache even though it
   * has two ways of access: each session is in a doubly linked list and an
   * lhash */
  SSL_SESSION_up_ref(c);
  /* if session c is in already in cache, we take back the increment later */

  CRYPTO_MUTEX_lock_write(&ctx->lock);
  if (!lh_SSL_SESSION_insert(ctx->sessions, &s, c)) {
    CRYPTO_MUTEX_unlock(&ctx->lock);
    return 0;
  }

  /* s != NULL iff we already had a session with the given PID. In this case, s
   * == c should hold (then we did not really modify ctx->sessions), or we're
   * in trouble. */
  if (s != NULL && s != c) {
    /* We *are* in trouble ... */
    SSL_SESSION_list_remove(ctx, s);
    SSL_SESSION_free(s);
    /* ... so pretend the other session did not exist in cache (we cannot
     * handle two SSL_SESSION structures with identical session ID in the same
     * cache, which could happen e.g. when two threads concurrently obtain the
     * same session from an external cache) */
    s = NULL;
  }

  /* Put at the head of the queue unless it is already in the cache */
  if (s == NULL) {
    SSL_SESSION_list_add(ctx, c);
  }

  if (s != NULL) {
    /* existing cache entry -- decrement previously incremented reference count
     * because it already takes into account the cache */
    SSL_SESSION_free(s); /* s == c */
    ret = 0;
  } else {
    /* new cache entry -- remove old ones if cache has become too large */
    ret = 1;

    if (SSL_CTX_sess_get_cache_size(ctx) > 0) {
      while (SSL_CTX_sess_number(ctx) > SSL_CTX_sess_get_cache_size(ctx)) {
        if (!remove_session_lock(ctx, ctx->session_cache_tail, 0)) {
          break;
        }
      }
    }
  }

  CRYPTO_MUTEX_unlock(&ctx->lock);
  return ret;
}
Example #2
0
void logsslstats(SSL *reference)
{
    char sglobal[1024];
    p_log(LOG_INFO,-1, lngtxt(613));
    if(reference==NULL)
        p_log(LOG_INFO,-1,lngtxt(614));
    else
    {
        if(SSL_get_shared_ciphers(reference,sglobal,1023)==NULL)
            strmncpy(sglobal,lngtxt(615),sizeof(sglobal));
        p_log(LOG_INFO,-1,lngtxt(616),sglobal);
    }
    p_log(LOG_INFO,-1, lngtxt(617),
          SSL_CTX_sess_number(srvctx)+SSL_CTX_sess_number(clnctx));
    p_log(LOG_INFO,-1, lngtxt(618),
          SSL_CTX_sess_connect(srvctx)+SSL_CTX_sess_connect(clnctx));
    p_log(LOG_INFO,-1, lngtxt(619),
          SSL_CTX_sess_connect_good(srvctx)+SSL_CTX_sess_connect_good(clnctx));
#if SSLEAY_VERSION_NUMBER >= 0x0922
    p_log(LOG_INFO,-1, lngtxt(620),
          SSL_CTX_sess_connect_renegotiate(srvctx)+SSL_CTX_sess_connect_renegotiate(clnctx));
#endif
    p_log(LOG_INFO,-1, lngtxt(621),
          SSL_CTX_sess_accept(srvctx)+SSL_CTX_sess_accept(clnctx));
    p_log(LOG_INFO,-1, lngtxt(622),
          SSL_CTX_sess_accept_good(srvctx)+SSL_CTX_sess_accept_good(clnctx));
#if SSLEAY_VERSION_NUMBER >= 0x0922
    p_log(LOG_INFO,-1, lngtxt(623),
          SSL_CTX_sess_accept_renegotiate(srvctx)+SSL_CTX_sess_accept_renegotiate(clnctx));
#endif
    p_log(LOG_INFO,-1, lngtxt(624), SSL_CTX_sess_hits(srvctx)+SSL_CTX_sess_hits(clnctx));
    p_log(LOG_INFO,-1, lngtxt(625), SSL_CTX_sess_misses(srvctx)+SSL_CTX_sess_misses(clnctx));
    p_log(LOG_INFO,-1, lngtxt(626), SSL_CTX_sess_timeouts(srvctx)+SSL_CTX_sess_timeouts(clnctx));
    p_log(LOG_INFO,-1, lngtxt(627));
    return;
}
Example #3
0
static void print_stats(FILE *fp, SSL_CTX *ctx)
{
    fprintf(fp, "%4ld items in the session cache\n",
            SSL_CTX_sess_number(ctx));
    fprintf(fp, "%4d client connects (SSL_connect())\n",
            SSL_CTX_sess_connect(ctx));
    fprintf(fp, "%4d client connects that finished\n",
            SSL_CTX_sess_connect_good(ctx));
    fprintf(fp, "%4d server connects (SSL_accept())\n",
            SSL_CTX_sess_accept(ctx));
    fprintf(fp, "%4d server connects that finished\n",
            SSL_CTX_sess_accept_good(ctx));
    fprintf(fp, "%4d session cache hits\n", SSL_CTX_sess_hits(ctx));
    fprintf(fp, "%4d session cache misses\n", SSL_CTX_sess_misses(ctx));
    fprintf(fp, "%4d session cache timeouts\n", SSL_CTX_sess_timeouts(ctx));
}
int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *session) {
  /* Although |session| is inserted into two structures (a doubly-linked list
   * and the hash table), |ctx| only takes one reference. */
  SSL_SESSION_up_ref(session);

  SSL_SESSION *old_session;
  CRYPTO_MUTEX_lock_write(&ctx->lock);
  if (!lh_SSL_SESSION_insert(ctx->sessions, &old_session, session)) {
    CRYPTO_MUTEX_unlock(&ctx->lock);
    SSL_SESSION_free(session);
    return 0;
  }

  if (old_session != NULL) {
    if (old_session == session) {
      /* |session| was already in the cache. */
      CRYPTO_MUTEX_unlock(&ctx->lock);
      SSL_SESSION_free(old_session);
      return 0;
    }

    /* There was a session ID collision. |old_session| must be removed from
     * the linked list and released. */
    SSL_SESSION_list_remove(ctx, old_session);
    SSL_SESSION_free(old_session);
  }

  SSL_SESSION_list_add(ctx, session);

  /* Enforce any cache size limits. */
  if (SSL_CTX_sess_get_cache_size(ctx) > 0) {
    while (SSL_CTX_sess_number(ctx) > SSL_CTX_sess_get_cache_size(ctx)) {
      if (!remove_session_lock(ctx, ctx->session_cache_tail, 0)) {
        break;
      }
    }
  }

  CRYPTO_MUTEX_unlock(&ctx->lock);
  return 1;
}
Example #5
0
static void print_stats(void) { /* print statistics */
    printf("%4ld items in the session cache\r\n",
        SSL_CTX_sess_number(pSSLSrvCtx));
    printf("%4ld client connects (SSL_connect())\r\n",
        SSL_CTX_sess_connect(pSSLSrvCtx));
    printf("%4ld client connects that finished\r\n",
        SSL_CTX_sess_connect_good(pSSLSrvCtx));
#if SSLEAY_VERSION_NUMBER >= 0x0922
    printf("%4ld client renegotiatations requested\r\n",
        SSL_CTX_sess_connect_renegotiate(pSSLSrvCtx));
#endif
    printf("%4ld server connects (SSL_accept())\r\n",
        SSL_CTX_sess_accept(pSSLSrvCtx));
    printf("%4ld server connects that finished\r\n",
        SSL_CTX_sess_accept_good(pSSLSrvCtx));
#if SSLEAY_VERSION_NUMBER >= 0x0922
    printf("%4ld server renegotiatiations requested\r\n",
        SSL_CTX_sess_accept_renegotiate(pSSLSrvCtx));
#endif
    printf("%4ld session cache hits\r\n", SSL_CTX_sess_hits(pSSLSrvCtx));
    printf("%4ld session cache misses\r\n", SSL_CTX_sess_misses(pSSLSrvCtx));
    printf("%4ld session cache timeouts\r\n", SSL_CTX_sess_timeouts(pSSLSrvCtx));
}
Example #6
0
/*
 *  call-seq:
 *     ctx.session_cache_stats -> Hash
 *
 */
static VALUE
ossl_sslctx_get_session_cache_stats(VALUE self)
{
    SSL_CTX *ctx;
    VALUE hash;

    Data_Get_Struct(self, SSL_CTX, ctx);

    hash = rb_hash_new();
    rb_hash_aset(hash, ID2SYM(rb_intern("cache_num")), LONG2NUM(SSL_CTX_sess_number(ctx)));
    rb_hash_aset(hash, ID2SYM(rb_intern("connect")), LONG2NUM(SSL_CTX_sess_connect(ctx)));
    rb_hash_aset(hash, ID2SYM(rb_intern("connect_good")), LONG2NUM(SSL_CTX_sess_connect_good(ctx)));
    rb_hash_aset(hash, ID2SYM(rb_intern("connect_renegotiate")), LONG2NUM(SSL_CTX_sess_connect_renegotiate(ctx)));
    rb_hash_aset(hash, ID2SYM(rb_intern("accept")), LONG2NUM(SSL_CTX_sess_accept(ctx)));
    rb_hash_aset(hash, ID2SYM(rb_intern("accept_good")), LONG2NUM(SSL_CTX_sess_accept_good(ctx)));
    rb_hash_aset(hash, ID2SYM(rb_intern("accept_renegotiate")), LONG2NUM(SSL_CTX_sess_accept_renegotiate(ctx)));
    rb_hash_aset(hash, ID2SYM(rb_intern("cache_hits")), LONG2NUM(SSL_CTX_sess_hits(ctx)));
    rb_hash_aset(hash, ID2SYM(rb_intern("cb_hits")), LONG2NUM(SSL_CTX_sess_cb_hits(ctx)));
    rb_hash_aset(hash, ID2SYM(rb_intern("cache_misses")), LONG2NUM(SSL_CTX_sess_misses(ctx)));
    rb_hash_aset(hash, ID2SYM(rb_intern("cache_full")), LONG2NUM(SSL_CTX_sess_cache_full(ctx)));
    rb_hash_aset(hash, ID2SYM(rb_intern("timeouts")), LONG2NUM(SSL_CTX_sess_timeouts(ctx)));

    return hash;
}
static void print_stats(BIO *bio, SSL_CTX *ssl_ctx)
{
	BIO_printf(bio,"%4ld items in the session cache\n",
		SSL_CTX_sess_number(ssl_ctx));
	BIO_printf(bio,"%4ld client connects (SSL_connect())\n",
		SSL_CTX_sess_connect(ssl_ctx));
	BIO_printf(bio,"%4ld client renegotiates (SSL_connect())\n",
		SSL_CTX_sess_connect_renegotiate(ssl_ctx));
	BIO_printf(bio,"%4ld client connects that finished\n",
		SSL_CTX_sess_connect_good(ssl_ctx));
	BIO_printf(bio,"%4ld server accepts (SSL_accept())\n",
		SSL_CTX_sess_accept(ssl_ctx));
	BIO_printf(bio,"%4ld server renegotiates (SSL_accept())\n",
		SSL_CTX_sess_accept_renegotiate(ssl_ctx));
	BIO_printf(bio,"%4ld server accepts that finished\n",
		SSL_CTX_sess_accept_good(ssl_ctx));
	BIO_printf(bio,"%4ld session cache hits\n",SSL_CTX_sess_hits(ssl_ctx));
	BIO_printf(bio,"%4ld session cache misses\n",SSL_CTX_sess_misses(ssl_ctx));
	BIO_printf(bio,"%4ld session cache timeouts\n",SSL_CTX_sess_timeouts(ssl_ctx));
	BIO_printf(bio,"%4ld callback cache hits\n",SSL_CTX_sess_cb_hits(ssl_ctx));
	BIO_printf(bio,"%4ld cache full overflows (%ld allowed)\n",
		SSL_CTX_sess_cache_full(ssl_ctx),
		SSL_CTX_sess_get_cache_size(ssl_ctx));
}
Example #8
0
NOEXPORT void info_callback(const SSL *ssl, int where, int ret) {
    CLI *c;
    SSL_CTX *ctx;
    const char *state_string;

    c=SSL_get_ex_data((SSL *)ssl, index_cli);
    if(c) {
        int state=SSL_get_state((SSL *)ssl);

#if 0
        s_log(LOG_DEBUG, "state = %x", state);
#endif

        /* log the client certificate request (if received) */
#ifndef SSL3_ST_CR_CERT_REQ_A
        if(state==TLS_ST_CR_CERT_REQ)
#else
        if(state==SSL3_ST_CR_CERT_REQ_A)
#endif
            print_client_CA_list(SSL_get_client_CA_list(ssl));
#ifndef SSL3_ST_CR_SRVR_DONE_A
        if(state==TLS_ST_CR_SRVR_DONE)
#else
        if(state==SSL3_ST_CR_SRVR_DONE_A)
#endif
            if(!SSL_get_client_CA_list(ssl))
                s_log(LOG_INFO, "Client certificate not requested");

        /* prevent renegotiation DoS attack */
        if((where&SSL_CB_HANDSHAKE_DONE)
                && c->reneg_state==RENEG_INIT) {
            /* first (initial) handshake was completed, remember this,
             * so that further renegotiation attempts can be detected */
            c->reneg_state=RENEG_ESTABLISHED;
        } else if((where&SSL_CB_ACCEPT_LOOP)
                && c->reneg_state==RENEG_ESTABLISHED) {
#ifndef SSL3_ST_SR_CLNT_HELLO_A
            if(state==TLS_ST_SR_CLNT_HELLO
                    || state==TLS_ST_SR_CLNT_HELLO) {
#else
            if(state==SSL3_ST_SR_CLNT_HELLO_A
                    || state==SSL23_ST_SR_CLNT_HELLO_A) {
#endif
                /* client hello received after initial handshake,
                 * this means renegotiation -> mark it */
                c->reneg_state=RENEG_DETECTED;
            }
        }

        if(c->opt->log_level<LOG_DEBUG) /* performance optimization */
            return;
    }

    if(where & SSL_CB_LOOP) {
        state_string=SSL_state_string_long(ssl);
        if(strcmp(state_string, "unknown state"))
            s_log(LOG_DEBUG, "SSL state (%s): %s",
                where & SSL_ST_CONNECT ? "connect" :
                where & SSL_ST_ACCEPT ? "accept" :
                "undefined", state_string);
    } else if(where & SSL_CB_ALERT) {
        s_log(LOG_DEBUG, "SSL alert (%s): %s: %s",
            where & SSL_CB_READ ? "read" : "write",
            SSL_alert_type_string_long(ret),
            SSL_alert_desc_string_long(ret));
    } else if(where==SSL_CB_HANDSHAKE_DONE) {
        ctx=SSL_get_SSL_CTX((SSL *)ssl);
        if(c->opt->option.client) {
            s_log(LOG_DEBUG, "%6ld client connect(s) requested",
                SSL_CTX_sess_connect(ctx));
            s_log(LOG_DEBUG, "%6ld client connect(s) succeeded",
                SSL_CTX_sess_connect_good(ctx));
            s_log(LOG_DEBUG, "%6ld client renegotiation(s) requested",
                SSL_CTX_sess_connect_renegotiate(ctx));
        } else {
            s_log(LOG_DEBUG, "%6ld server accept(s) requested",
                SSL_CTX_sess_accept(ctx));
            s_log(LOG_DEBUG, "%6ld server accept(s) succeeded",
                SSL_CTX_sess_accept_good(ctx));
            s_log(LOG_DEBUG, "%6ld server renegotiation(s) requested",
                SSL_CTX_sess_accept_renegotiate(ctx));
        }
        /* according to the source it not only includes internal
           and external session caches, but also session tickets */
        s_log(LOG_DEBUG, "%6ld session reuse(s)",
            SSL_CTX_sess_hits(ctx));
        if(!c->opt->option.client) { /* server session cache stats */
            s_log(LOG_DEBUG, "%6ld internal session cache item(s)",
                SSL_CTX_sess_number(ctx));
            s_log(LOG_DEBUG, "%6ld internal session cache fill-up(s)",
                SSL_CTX_sess_cache_full(ctx));
            s_log(LOG_DEBUG, "%6ld internal session cache miss(es)",
                SSL_CTX_sess_misses(ctx));
            s_log(LOG_DEBUG, "%6ld external session cache hit(s)",
                SSL_CTX_sess_cb_hits(ctx));
            s_log(LOG_DEBUG, "%6ld expired session(s) retrieved",
                SSL_CTX_sess_timeouts(ctx));
        }
    }
}

/**************************************** SSL error reporting */

void sslerror(char *txt) { /* OpenSSL error handler */
    unsigned long err;

    err=ERR_get_error();
    if(err) {
        sslerror_queue();
        sslerror_log(err, txt);
    } else {
        s_log(LOG_ERR, "%s: Peer suddenly disconnected", txt);
    }
}
/*
 *	Send an initial eap-tls request to the peer.
 *
 *	Frame eap reply packet.
 *	len = header + type + tls_typedata
 *	tls_typedata = flags(Start (S) bit set, and no data)
 *
 *	Once having received the peer's Identity, the EAP server MUST
 *	respond with an EAP-TLS/Start packet, which is an
 *	EAP-Request packet with EAP-Type=EAP-TLS, the Start (S) bit
 *	set, and no data.  The EAP-TLS conversation will then begin,
 *	with the peer sending an EAP-Response packet with
 *	EAP-Type = EAP-TLS.  The data field of that packet will
 *	be the TLS data.
 *
 *	Fragment length is Framed-MTU - 4.
 *
 *	http://mail.frascone.com/pipermail/public/eap/2003-July/001426.html
 */
static int eaptls_initiate(void *type_arg, EAP_HANDLER *handler)
{
	int		status;
	tls_session_t	*ssn;
	eap_tls_t	*inst;
	VALUE_PAIR	*vp;
	int		client_cert = TRUE;
	int		verify_mode = 0;
	REQUEST		*request = handler->request;

	inst = (eap_tls_t *)type_arg;

	handler->tls = TRUE;
	handler->finished = FALSE;

	/*
	 *	Manually flush the sessions every so often.  If HALF
	 *	of the session lifetime has passed since we last
	 *	flushed, then flush it again.
	 *
	 *	FIXME: Also do it every N sessions?
	 */
	if (inst->conf->session_cache_enable &&
	    ((inst->conf->session_last_flushed + (inst->conf->session_timeout * 1800)) <= request->timestamp)) {
		RDEBUG2("Flushing SSL sessions (of #%ld)",
			SSL_CTX_sess_number(inst->ctx));

		SSL_CTX_flush_sessions(inst->ctx, request->timestamp);
		inst->conf->session_last_flushed = request->timestamp;
	}

	/*
	 *	If we're TTLS or PEAP, then do NOT require a client
	 *	certificate.
	 *
	 *	FIXME: This should be more configurable.
	 */
	if (handler->eap_type != PW_EAP_TLS) {
		vp = pairfind(handler->request->config_items,
			      PW_EAP_TLS_REQUIRE_CLIENT_CERT, 0);
		if (!vp) {
			client_cert = FALSE;
		} else {
			client_cert = vp->vp_integer;
		}
	}

	/*
	 *	Every new session is started only from EAP-TLS-START.
	 *	Before Sending EAP-TLS-START, open a new SSL session.
	 *	Create all the required data structures & store them
	 *	in Opaque.  So that we can use these data structures
	 *	when we get the response
	 */
	ssn = eaptls_new_session(inst->ctx, client_cert);
	if (!ssn) {
		return 0;
	}

	/*
	 *	Verify the peer certificate, if asked.
	 */
	if (client_cert) {
		RDEBUG2("Requiring client certificate");
		verify_mode = SSL_VERIFY_PEER;
		verify_mode |= SSL_VERIFY_FAIL_IF_NO_PEER_CERT;
		verify_mode |= SSL_VERIFY_CLIENT_ONCE;
	}
	SSL_set_verify(ssn->ssl, verify_mode, cbtls_verify);

	/*
	 *	Create a structure for all the items required to be
	 *	verified for each client and set that as opaque data
	 *	structure.
	 *
	 *	NOTE: If we want to set each item sepearately then
	 *	this index should be global.
	 */
	SSL_set_ex_data(ssn->ssl, 0, (void *)handler);
	SSL_set_ex_data(ssn->ssl, 1, (void *)inst->conf);
#ifdef HAVE_OPENSSL_OCSP_H
	SSL_set_ex_data(ssn->ssl, 2, (void *)inst->store);
#endif

	ssn->length_flag = inst->conf->include_length;

	/*
	 *	We use default fragment size, unless the Framed-MTU
	 *	tells us it's too big.  Note that we do NOT account
	 *	for the EAP-TLS headers if conf->fragment_size is
	 *	large, because that config item looks to be confusing.
	 *
	 *	i.e. it should REALLY be called MTU, and the code here
	 *	should figure out what that means for TLS fragment size.
	 *	asking the administrator to know the internal details
	 *	of EAP-TLS in order to calculate fragment sizes is
	 *	just too much.
	 */
	ssn->offset = inst->conf->fragment_size;
	vp = pairfind(handler->request->packet->vps, PW_FRAMED_MTU, 0);
	if (vp && ((vp->vp_integer - 14) < ssn->offset)) {
		/*
		 *	Discount the Framed-MTU by:
		 *	 4 : EAPOL header
		 *	 4 : EAP header (code + id + length)
		 *	 1 : EAP type == EAP-TLS
		 *	 1 : EAP-TLS Flags
		 *	 4 : EAP-TLS Message length
		 *	    (even if conf->include_length == 0,
		 *	     just to be lazy).
		 *	---
		 *	14
		 */
		ssn->offset = vp->vp_integer - 14;
	}

	handler->opaque = ((void *)ssn);
	handler->free_opaque = session_free;

	RDEBUG2("Initiate");

	/*
	 *	Set up type-specific information.
	 */
	switch (handler->eap_type) {
	case PW_EAP_TLS:
	default:
		ssn->prf_label = "client EAP encryption";
		break;

	case PW_EAP_TTLS:
		ssn->prf_label = "ttls keying material";
		break;

		/*
		 *	PEAP-specific breakage.
		 */
	case PW_EAP_PEAP:
		/*
		 *	As it is a poorly designed protocol, PEAP uses
		 *	bits in the TLS header to indicate PEAP
		 *	version numbers.  For now, we only support
		 *	PEAP version 0, so it doesn't matter too much.
		 *	However, if we support later versions of PEAP,
		 *	we will need this flag to indicate which
		 *	version we're currently dealing with.
		 */
		ssn->peap_flag = 0x00;

		/*
		 *	PEAP version 0 requires 'include_length = no',
		 *	so rather than hoping the user figures it out,
		 *	we force it here.
		 */
		ssn->length_flag = 0;

		ssn->prf_label = "client EAP encryption";
		break;
	}

	if (inst->conf->session_cache_enable) {
		ssn->allow_session_resumption = 1; /* otherwise it's zero */
	}

	/*
	 *	TLS session initialization is over.  Now handle TLS
	 *	related handshaking or application data.
	 */
	status = eaptls_start(handler->eap_ds, ssn->peap_flag);
	RDEBUG2("Start returned %d", status);
	if (status == 0)
		return 0;

	/*
	 *	The next stage to process the packet.
	 */
	handler->stage = AUTHENTICATE;

	return 1;
}
Example #10
0
File: ctx.c Project: Jimdo/stunnel
NOEXPORT void info_callback(
#if OPENSSL_VERSION_NUMBER>=0x0090700fL
        const
#endif
        SSL *ssl, int where, int ret) {
    CLI *c;

    c=SSL_get_ex_data(ssl, cli_index);
    if(c) {
        if((where&SSL_CB_HANDSHAKE_DONE)
                && c->reneg_state==RENEG_INIT) {
            /* first (initial) handshake was completed, remember this,
             * so that further renegotiation attempts can be detected */
            c->reneg_state=RENEG_ESTABLISHED;
        } else if((where&SSL_CB_ACCEPT_LOOP)
                && c->reneg_state==RENEG_ESTABLISHED) {
            int state=SSL_get_state(ssl);

            if(state==SSL3_ST_SR_CLNT_HELLO_A
                    || state==SSL23_ST_SR_CLNT_HELLO_A) {
                /* client hello received after initial handshake,
                 * this means renegotiation -> mark it */
                c->reneg_state=RENEG_DETECTED;
            }
        }
    }

    if(global_options.debug_level<LOG_DEBUG)
        return; /* performance optimization */

    if(where & SSL_CB_LOOP) {
        s_log(LOG_DEBUG, "SSL state (%s): %s",
            where & SSL_ST_CONNECT ? "connect" :
            where & SSL_ST_ACCEPT ? "accept" :
            "undefined", SSL_state_string_long(ssl));
    } else if(where & SSL_CB_ALERT) {
        s_log(LOG_DEBUG, "SSL alert (%s): %s: %s",
            where & SSL_CB_READ ? "read" : "write",
            SSL_alert_type_string_long(ret),
            SSL_alert_desc_string_long(ret));
    } else if(where==SSL_CB_HANDSHAKE_DONE) {
        s_log(LOG_DEBUG, "%4ld items in the session cache",
            SSL_CTX_sess_number(ssl->ctx));
        s_log(LOG_DEBUG, "%4ld client connects (SSL_connect())",
            SSL_CTX_sess_connect(ssl->ctx));
        s_log(LOG_DEBUG, "%4ld client connects that finished",
            SSL_CTX_sess_connect_good(ssl->ctx));
        s_log(LOG_DEBUG, "%4ld client renegotiations requested",
            SSL_CTX_sess_connect_renegotiate(ssl->ctx));
        s_log(LOG_DEBUG, "%4ld server connects (SSL_accept())",
            SSL_CTX_sess_accept(ssl->ctx));
        s_log(LOG_DEBUG, "%4ld server connects that finished",
            SSL_CTX_sess_accept_good(ssl->ctx));
        s_log(LOG_DEBUG, "%4ld server renegotiations requested",
            SSL_CTX_sess_accept_renegotiate(ssl->ctx));
        s_log(LOG_DEBUG, "%4ld session cache hits",
            SSL_CTX_sess_hits(ssl->ctx));
        s_log(LOG_DEBUG, "%4ld external session cache hits",
            SSL_CTX_sess_cb_hits(ssl->ctx));
        s_log(LOG_DEBUG, "%4ld session cache misses",
            SSL_CTX_sess_misses(ssl->ctx));
        s_log(LOG_DEBUG, "%4ld session cache timeouts",
            SSL_CTX_sess_timeouts(ssl->ctx));
    }
}
Example #11
0
int SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c)
{
    int ret = 0;
    SSL_SESSION *s;

    /*
     * add just 1 reference count for the SSL_CTX's session cache even though
     * it has two ways of access: each session is in a doubly linked list and
     * an lhash
     */
    SSL_SESSION_up_ref(c);
    /*
     * if session c is in already in cache, we take back the increment later
     */

    CRYPTO_THREAD_write_lock(ctx->lock);
    s = lh_SSL_SESSION_insert(ctx->sessions, c);

    /*
     * s != NULL iff we already had a session with the given PID. In this
     * case, s == c should hold (then we did not really modify
     * ctx->sessions), or we're in trouble.
     */
    if (s != NULL && s != c) {
        /* We *are* in trouble ... */
        SSL_SESSION_list_remove(ctx, s);
        SSL_SESSION_free(s);
        /*
         * ... so pretend the other session did not exist in cache (we cannot
         * handle two SSL_SESSION structures with identical session ID in the
         * same cache, which could happen e.g. when two threads concurrently
         * obtain the same session from an external cache)
         */
        s = NULL;
    } else if (s == NULL &&
               lh_SSL_SESSION_retrieve(ctx->sessions, c) == NULL) {
        /* s == NULL can also mean OOM error in lh_SSL_SESSION_insert ... */

        /*
         * ... so take back the extra reference and also don't add
         * the session to the SSL_SESSION_list at this time
         */
        s = c;
    }

    /* Put at the head of the queue unless it is already in the cache */
    if (s == NULL)
        SSL_SESSION_list_add(ctx, c);

    if (s != NULL) {
        /*
         * existing cache entry -- decrement previously incremented reference
         * count because it already takes into account the cache
         */

        SSL_SESSION_free(s);    /* s == c */
        ret = 0;
    } else {
        /*
         * new cache entry -- remove old ones if cache has become too large
         */

        ret = 1;

        if (SSL_CTX_sess_get_cache_size(ctx) > 0) {
            while (SSL_CTX_sess_number(ctx) > SSL_CTX_sess_get_cache_size(ctx)) {
                if (!remove_session_lock(ctx, ctx->session_cache_tail, 0))
                    break;
                else
                    ctx->stats.sess_cache_full++;
            }
        }
    }
    CRYPTO_THREAD_unlock(ctx->lock);
    return ret;
}
Example #12
0
NOEXPORT void info_callback(const SSL *ssl, int where, int ret) {
    CLI *c;
    SSL_CTX *ctx;

    c=SSL_get_ex_data((SSL *)ssl, index_cli);
    if(c) {
        if((where&SSL_CB_HANDSHAKE_DONE)
                && c->reneg_state==RENEG_INIT) {
            /* first (initial) handshake was completed, remember this,
             * so that further renegotiation attempts can be detected */
            c->reneg_state=RENEG_ESTABLISHED;
        } else if((where&SSL_CB_ACCEPT_LOOP)
                && c->reneg_state==RENEG_ESTABLISHED) {
            int state=SSL_get_state((SSL *)ssl);

            if(state==SSL3_ST_SR_CLNT_HELLO_A
                    || state==SSL23_ST_SR_CLNT_HELLO_A) {
                /* client hello received after initial handshake,
                 * this means renegotiation -> mark it */
                c->reneg_state=RENEG_DETECTED;
            }
        }
        if(c->opt->log_level<LOG_DEBUG)
            return; /* performance optimization */
    }

    if(where & SSL_CB_LOOP) {
        s_log(LOG_DEBUG, "SSL state (%s): %s",
            where & SSL_ST_CONNECT ? "connect" :
            where & SSL_ST_ACCEPT ? "accept" :
            "undefined", SSL_state_string_long(ssl));
    } else if(where & SSL_CB_ALERT) {
        s_log(LOG_DEBUG, "SSL alert (%s): %s: %s",
            where & SSL_CB_READ ? "read" : "write",
            SSL_alert_type_string_long(ret),
            SSL_alert_desc_string_long(ret));
    } else if(where==SSL_CB_HANDSHAKE_DONE) {
        ctx=SSL_get_SSL_CTX((SSL *)ssl);
        if(c->opt->option.client) {
            s_log(LOG_DEBUG, "%4ld client connect(s) requested",
                SSL_CTX_sess_connect(ctx));
            s_log(LOG_DEBUG, "%4ld client connect(s) succeeded",
                SSL_CTX_sess_connect_good(ctx));
            s_log(LOG_DEBUG, "%4ld client renegotiation(s) requested",
                SSL_CTX_sess_connect_renegotiate(ctx));
        } else {
            s_log(LOG_DEBUG, "%4ld server accept(s) requested",
                SSL_CTX_sess_accept(ctx));
            s_log(LOG_DEBUG, "%4ld server accept(s) succeeded",
                SSL_CTX_sess_accept_good(ctx));
            s_log(LOG_DEBUG, "%4ld server renegotiation(s) requested",
                SSL_CTX_sess_accept_renegotiate(ctx));
        }
        /* according to the source it not only includes internal
           and external session caches, but also session tickets */
        s_log(LOG_DEBUG, "%4ld session reuse(s)",
            SSL_CTX_sess_hits(ctx));
        if(!c->opt->option.client) { /* server session cache stats */
            s_log(LOG_DEBUG, "%4ld internal session cache item(s)",
                SSL_CTX_sess_number(ctx));
            s_log(LOG_DEBUG, "%4ld internal session cache fill-up(s)",
                SSL_CTX_sess_cache_full(ctx));
            s_log(LOG_DEBUG, "%4ld internal session cache miss(es)",
                SSL_CTX_sess_misses(ctx));
            s_log(LOG_DEBUG, "%4ld external session cache hit(s)",
                SSL_CTX_sess_cb_hits(ctx));
            s_log(LOG_DEBUG, "%4ld expired session(s) retrieved",
                SSL_CTX_sess_timeouts(ctx));
        }
    }
}
Example #13
0
int
SSL_CTX_add_session(SSL_CTX *ctx, SSL_SESSION *c)
{
	int ret = 0;
	SSL_SESSION *s;

	/*
	 * Add just 1 reference count for the SSL_CTX's session cache
	 * even though it has two ways of access: each session is in a
	 * doubly linked list and an lhash.
	 */
	CRYPTO_add(&c->references, 1, CRYPTO_LOCK_SSL_SESSION);

	/*
	 * If session c is in already in cache, we take back the increment
	 * later.
	 */
	CRYPTO_w_lock(CRYPTO_LOCK_SSL_CTX);
	s = lh_SSL_SESSION_insert(ctx->internal->sessions, c);

	/*
	 * s != NULL iff we already had a session with the given PID.
	 * In this case, s == c should hold (then we did not really modify
	 * ctx->internal->sessions), or we're in trouble.
	 */
	if (s != NULL && s != c) {
		/* We *are* in trouble ... */
		SSL_SESSION_list_remove(ctx, s);
		SSL_SESSION_free(s);
		/*
		 * ... so pretend the other session did not exist in cache
		 * (we cannot handle two SSL_SESSION structures with identical
		 * session ID in the same cache, which could happen e.g. when
		 * two threads concurrently obtain the same session from an
		 * external cache).
		 */
		s = NULL;
	}

	/* Put at the head of the queue unless it is already in the cache */
	if (s == NULL)
		SSL_SESSION_list_add(ctx, c);

	if (s != NULL) {
		/*
		 * existing cache entry -- decrement previously incremented
		 * reference count because it already takes into account the
		 * cache.
		 */
		SSL_SESSION_free(s); /* s == c */
		ret = 0;
	} else {
		/*
		 * New cache entry -- remove old ones if cache has become
		 * too large.
		 */

		ret = 1;

		if (SSL_CTX_sess_get_cache_size(ctx) > 0) {
			while (SSL_CTX_sess_number(ctx) >
			    SSL_CTX_sess_get_cache_size(ctx)) {
				if (!remove_session_lock(ctx,
				    ctx->internal->session_cache_tail, 0))
					break;
				else
					ctx->internal->stats.sess_cache_full++;
			}
		}
	}
	CRYPTO_w_unlock(CRYPTO_LOCK_SSL_CTX);
	return (ret);
}