Esempio n. 1
0
SSL_SESSION *ssl_scache_retrieve(server_rec *s, UCHAR *id, int idlen,
                                 apr_pool_t *p)
{
    SSLModConfigRec *mc = myModConfig(s);
    unsigned char dest[SSL_SESSION_MAX_DER];
    unsigned int destlen = SSL_SESSION_MAX_DER;
    const unsigned char *ptr;
    apr_status_t rv;

    if (mc->sesscache->flags & AP_SOCACHE_FLAG_NOTMPSAFE) {
        ssl_mutex_on(s);
    }

    rv = mc->sesscache->retrieve(mc->sesscache_context, s, id, idlen,
                                 dest, &destlen, p);

    if (mc->sesscache->flags & AP_SOCACHE_FLAG_NOTMPSAFE) {
        ssl_mutex_off(s);
    }

    if (rv != APR_SUCCESS) {
        return NULL;
    }

    ptr = dest;

    return d2i_SSL_SESSION(NULL, &ptr, destlen);
}
Esempio n. 2
0
SSL_SESSION *ssl_scache_dc_retrieve(server_rec *s, UCHAR *id, int idlen)
{
    unsigned char der[SSL_SESSION_MAX_DER];
    unsigned int der_len;
    SSL_SESSION *pSession;
    MODSSL_D2I_SSL_SESSION_CONST unsigned char *pder = der;
    SSLModConfigRec *mc = myModConfig(s);
    DC_CTX *ctx = mc->tSessionCacheDataTable;

    /* Retrieve any corresponding session from the distributed cache context */
    if (!DC_CTX_get_session(ctx, id, idlen, der, SSL_SESSION_MAX_DER,
                            &der_len)) {
        ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "distributed scache 'get_session' MISS");
        return NULL;
    }
    if (der_len > SSL_SESSION_MAX_DER) {
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "distributed scache 'get_session' OVERFLOW");
        return NULL;
    }
    pSession = d2i_SSL_SESSION(NULL, &pder, der_len);
    if (!pSession) {
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, s, "distributed scache 'get_session' CORRUPT");
        return NULL;
    }
    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s, "distributed scache 'get_session' HIT");
    return pSession;
}
Esempio n. 3
0
SSLSessionImpl::SSLSessionImpl(const std::string& serializedSession) {
  auto sessionData =
      reinterpret_cast<const unsigned char*>(serializedSession.data());
  auto longLen = long(serializedSession.length());
  if ((session_ = d2i_SSL_SESSION(nullptr, &sessionData, longLen)) == nullptr) {
    throw std::runtime_error("Cannot deserialize SSLSession string");
  }
}
static BOOL shmcb_subcache_remove(server_rec *s, SHMCBHeader *header,
                                  SHMCBSubcache *subcache,
                                  UCHAR *id, unsigned int idlen)
{
    unsigned int pos;
    unsigned int loop = 0;
    BOOL to_return = FALSE;

    /* Unlike the others, we don't do an expire-run first. This is to keep
     * consistent statistics where a "remove" operation may actually be the
     * higher layer spotting an expiry issue prior to us. Our caller is
     * handling stats, so a failure return would be inconsistent if the
     * intended session was in fact removed by an expiry run. */

    pos = subcache->idx_pos;
    while (!to_return && (loop < subcache->idx_used)) {
        SHMCBIndex *idx = SHMCB_INDEX(subcache, pos);
        /* Only consider 'idx' if the s_id2 byte matches and it's not already
         * removed - easiest way to avoid costly ASN decodings. */
        if ((idx->s_id2 == id[1]) && !idx->removed) {
            SSL_SESSION *pSession;
            unsigned char *s_id;
            unsigned int s_idlen;
            unsigned char tempasn[SSL_SESSION_MAX_DER];
            MODSSL_D2I_SSL_SESSION_CONST unsigned char *ptr = tempasn;

            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                         "possible match at idx=%d, data=%d", pos, idx->data_pos);
            /* Copy the data */
            shmcb_cyclic_cton_memcpy(header->subcache_data_size,
                                     tempasn, SHMCB_DATA(header, subcache),
                                     idx->data_pos, idx->data_used);
            /* Decode the session */
            pSession = d2i_SSL_SESSION(NULL, &ptr, idx->data_used);
            if (!pSession) {
                ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
                             "shmcb_subcache_remove internal error");
                return FALSE;
            }
            s_id = SSL_SESSION_get_session_id(pSession);
            s_idlen = SSL_SESSION_get_session_id_length(pSession);
            if (s_idlen == idlen && memcmp(s_id, id, idlen) == 0) {
                /* Found the matching session, remove it quietly. */
                idx->removed = 1;
                to_return = TRUE;
                ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                             "shmcb_subcache_remove removing matching session");
            }
            SSL_SESSION_free(pSession);
        }
        /* Increment */
        loop++;
        pos = SHMCB_CYCLIC_INCREMENT(pos, 1, header->index_num);
    }

    return to_return;
}
Esempio n. 5
0
std::pair<SSL_SESSION*, size_t> getSessionWithTicket() {
  const unsigned char* p = kSessionDataWithTicket;
  size_t sessionDataWithTicketLen = sizeof(kSessionDataWithTicket);
  auto s = d2i_SSL_SESSION(nullptr, &p, sessionDataWithTicketLen);
  CHECK(isSameSession(
        std::make_pair(s, sessionDataWithTicketLen),
        std::make_pair(s, sessionDataWithTicketLen)));
  return std::make_pair(s, sessionDataWithTicketLen);
}
static SSL_SESSION *shmcb_subcache_retrieve(server_rec *s, SHMCBHeader *header,
                                            SHMCBSubcache *subcache, UCHAR *id,
                                            unsigned int idlen)
{
    unsigned int pos;
    unsigned int loop = 0;

    /* If there are entries to expire, ditch them first. */
    shmcb_subcache_expire(s, header, subcache);
    pos = subcache->idx_pos;

    while (loop < subcache->idx_used) {
        SHMCBIndex *idx = SHMCB_INDEX(subcache, pos);

        /* Only consider 'idx' if;
         * (a) the s_id2 byte matches
         * (b) the "removed" flag isn't set.
         */
        if ((idx->s_id2 == id[1]) && !idx->removed) {
            SSL_SESSION *pSession;
            unsigned char *s_id;
            unsigned int s_idlen;
            unsigned char tempasn[SSL_SESSION_MAX_DER];
            MODSSL_D2I_SSL_SESSION_CONST unsigned char *ptr = tempasn;

            ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                         "possible match at idx=%d, data=%d", pos, idx->data_pos);
            /* Copy the data */
            shmcb_cyclic_cton_memcpy(header->subcache_data_size,
                                     tempasn, SHMCB_DATA(header, subcache),
                                     idx->data_pos, idx->data_used);
            /* Decode the session */
            pSession = d2i_SSL_SESSION(NULL, &ptr, idx->data_used);
            if (!pSession) {
                ap_log_error(APLOG_MARK, APLOG_ERR, 0, s,
                             "shmcb_subcache_retrieve internal error");
                return NULL;
            }
            s_id = SSL_SESSION_get_session_id(pSession);
            s_idlen = SSL_SESSION_get_session_id_length(pSession);
            if (s_idlen == idlen && memcmp(s_id, id, idlen) == 0) {
                /* Found the matching session */
                ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                             "shmcb_subcache_retrieve returning matching session");
                return pSession;
            }
            SSL_SESSION_free(pSession);
        }
        /* Increment */
        loop++;
        pos = SHMCB_CYCLIC_INCREMENT(pos, 1, header->index_num);
    }

    ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, s,
                 "shmcb_subcache_retrieve found no match");
    return NULL;
}
Esempio n. 7
0
void SSLSessionCacheManager::restoreSession(
    SSLCacheProvider::CacheContext* cacheCtx,
    const uint8_t* data,
    size_t length) {
  cacheCtx->session = d2i_SSL_SESSION(nullptr, &data, length);
  restartSSLAccept(cacheCtx);

  /* Insert in the LRU after restarting all clients.  The stats logic
   * in getSession would treat this as a local hit otherwise.
   */
  localCache_->storeSession(cacheCtx->sessionId, cacheCtx->session, stats_);
  delete cacheCtx;
}
Esempio n. 8
0
void SSLSessionCacheManager::onGetSuccess(
    SSLCacheProvider::CacheContext* cacheCtx,
    const std::string& value) {
    const uint8_t* cp = (uint8_t*)value.data();
    cacheCtx->session = d2i_SSL_SESSION(nullptr, &cp, value.length());
    restartSSLAccept(cacheCtx);

    /* Insert in the LRU after restarting all clients.  The stats logic
     * in getSession would treat this as a local hit otherwise.
     */
    localCache_->storeSession(cacheCtx->sessionId, cacheCtx->session, stats_);
    delete cacheCtx;
}
Esempio n. 9
0
SSL_SESSION *uwsgi_ssl_session_get_cb(SSL *ssl, unsigned char *key, int keylen, int *copy) {

        uint64_t valsize = 0;

        *copy = 0;
        uwsgi_rlock(uwsgi.ssl_sessions_cache->lock);
        char *value = uwsgi_cache_get2(uwsgi.ssl_sessions_cache, (char *)key, keylen, &valsize);
        if (!value) {
                uwsgi_rwunlock(uwsgi.ssl_sessions_cache->lock);
                if (uwsgi.ssl_verbose) {
                        uwsgi_log("[uwsgi-ssl] cache miss\n");
                }
                return NULL;
        }
#if (OPENSSL_VERSION_NUMBER >= 0x0090800fL)
        SSL_SESSION *sess = d2i_SSL_SESSION(NULL, (const unsigned char **)&value, valsize);
#else
        SSL_SESSION *sess = d2i_SSL_SESSION(NULL, (unsigned char **)&value, valsize);
#endif
        uwsgi_rwunlock(uwsgi.ssl_sessions_cache->lock);
        return sess;
}
Esempio n. 10
0
void h2o_socket_ssl_resume_server_handshake(h2o_socket_t *sock, h2o_iovec_t session_data)
{
    if (session_data.len != 0) {
        const unsigned char *p = (void *)session_data.base;
        sock->ssl->handshake.server.async_resumption.session_data = d2i_SSL_SESSION(NULL, &p, (long)session_data.len);
        /* FIXME warn on failure */
    }

    sock->ssl->handshake.server.async_resumption.state = ASYNC_RESUMPTION_STATE_COMPLETE;
    proceed_handshake(sock, 0);

    if (sock->ssl->handshake.server.async_resumption.session_data != NULL) {
        SSL_SESSION_free(sock->ssl->handshake.server.async_resumption.session_data);
        sock->ssl->handshake.server.async_resumption.session_data = NULL;
    }
}
Esempio n. 11
0
static SSL_SESSION *generate_dtls_session(struct openconnect_info *vpninfo,
					  int dtlsver, const SSL_CIPHER *cipher)
{
	struct oc_text_buf *buf = buf_alloc();
	SSL_SESSION *dtls_session;
	const unsigned char *asn;
	uint16_t cid;

	buf_append_bytes(buf, "\x30\x80", 2); // SEQUENCE, indeterminate length
	buf_append_INTEGER(buf, 1 /* SSL_SESSION_ASN1_VERSION */);
	buf_append_INTEGER(buf, dtlsver);
	store_be16(&cid, SSL_CIPHER_get_id(cipher) & 0xffff);
	buf_append_OCTET_STRING(buf, &cid, 2);
	buf_append_OCTET_STRING(buf, vpninfo->dtls_session_id,
				sizeof(vpninfo->dtls_session_id));
	buf_append_OCTET_STRING(buf, vpninfo->dtls_secret,
				sizeof(vpninfo->dtls_secret));
	/* If the length actually fits in one byte (which it should), do
	 * it that way.  Else, leave it indeterminate and add two
	 * end-of-contents octets to mark the end of the SEQUENCE. */
	if (!buf_error(buf) && buf->pos <= 0x80)
		buf->data[1] = buf->pos - 2;
	else
		buf_append_bytes(buf, "\0\0", 2);

	if (buf_error(buf)) {
		vpn_progress(vpninfo, PRG_ERR,
			     _("Failed to create SSL_SESSION ASN.1 for OpenSSL: %s\n"),
			     strerror(buf_error(buf)));
		buf_free(buf);
		return NULL;
	}

	asn = (void *)buf->data;
	dtls_session = d2i_SSL_SESSION(NULL, &asn, buf->pos);
	buf_free(buf);
	if (!dtls_session) {
		vpn_progress(vpninfo, PRG_ERR,
			     _("OpenSSL failed to parse SSL_SESSION ASN.1\n"));
		openconnect_report_ssl_errors(vpninfo);
		return NULL;
	}

	return dtls_session;
}
SSL_SESSION *ssl_scache_shmht_retrieve(server_rec *s, UCHAR *id, int idlen)
{
    SSLModConfigRec *mc = myModConfig();
    void *vp;
    SSL_SESSION *sess = NULL;
    UCHAR *ucpData;
    int nData;
    time_t expiry;
    time_t now;
    int n;

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

    /* lookup key in table */
    ssl_mutex_on(s);
    if (table_retrieve(mc->tSessionCacheDataTable,
                       id, idlen, &vp, &n) != TABLE_ERROR_NONE) {
        ssl_mutex_off(s);
        return NULL;
    }

    /* copy over the information to the SCI */
    nData = n-sizeof(time_t);
    ucpData = (UCHAR *)malloc(nData);
    if (ucpData == NULL) {
        ssl_mutex_off(s);
        return NULL;
    }
    memcpy(&expiry, vp, sizeof(time_t));
    memcpy(ucpData, (char *)vp+sizeof(time_t), nData);
    ssl_mutex_off(s);

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

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

    return sess;
}
Esempio n. 13
0
NOEXPORT SSL_SESSION *cache_get(SSL *ssl,
        const unsigned char *key, int key_len) {
    unsigned char *val, *val_tmp=NULL;
    ssize_t val_len=0;
    SSL_SESSION *sess;

    cache_transfer(SSL_get_SSL_CTX(ssl), CACHE_CMD_GET, 0,
        key, (size_t)key_len, NULL, 0, &val, (size_t *)&val_len);
    if(!val)
        return NULL;
    val_tmp=val;
    sess=d2i_SSL_SESSION(NULL,
#if OPENSSL_VERSION_NUMBER>=0x0090800fL
        (const unsigned char **)
#endif /* OpenSSL version >= 0.8.0 */
        &val_tmp, (long)val_len);
    str_free(val);
    return sess;
}
/* de-serialized a SSL session and set it back to the request at lua context */
int
ngx_http_lua_ffi_ssl_set_serialized_session(ngx_http_request_t *r,
    const unsigned char *data, int len, char **err)
{
    u_char                          *p;
    u_char                           buf[NGX_SSL_MAX_SESSION_SIZE];
    ngx_ssl_conn_t                  *ssl_conn;
    ngx_connection_t                *c;
    ngx_ssl_session_t               *session = NULL;
    ngx_http_lua_ssl_ctx_t          *cctx;

    c = r->connection;

    if (c == NULL || c->ssl == NULL) {
        *err = "bad request";
        return NGX_ERROR;
    }

    ssl_conn = c->ssl->connection;
    if (ssl_conn == NULL) {
        *err = "bad ssl conn";
        return NGX_ERROR;
    }

    ngx_memcpy(buf, data, len);
    p = buf;
    session = d2i_SSL_SESSION(NULL, (const unsigned char **)&p,  len);
    if (session == NULL) {
        ERR_clear_error();
        *err = "failed to de-serialize session";
        return NGX_ERROR;
    }

    cctx = ngx_http_lua_ssl_get_ctx(c->ssl->connection);
    if (cctx == NULL) {
        *err = "bad lua context";
        return NGX_ERROR;
    }

    cctx->session = session;

    return NGX_OK;
}
Esempio n. 15
0
std::vector<std::pair<SSL_SESSION*, size_t>> getSessions() {
  std::vector<std::pair<SSL_SESSION*, size_t>> sessions;

  for (size_t i = 0; i < kNumSessions; ++i) {
    const unsigned char* p = kSessionData[i];
    auto s = d2i_SSL_SESSION(nullptr, &p, kSessionDataLen);
    CHECK(s) << "Invalid session " << i;
    sessions.emplace_back(s, kSessionDataLen);

    // Make sure the same session compares same to itself.
    CHECK(isSameSession(sessions[i], sessions[i]));
  }
  // Make sure all sessions are different from each other
  CHECK(!isSameSession(sessions[0], sessions[1]));
  CHECK(!isSameSession(sessions[1], sessions[2]));
  CHECK(!isSameSession(sessions[2], sessions[0]));

  return sessions;
}
Esempio n. 16
0
static cache_val_t
cachessess_unpackverify_val_cb(cache_val_t val, int copy)
{
	dynbuf_t *valbuf = val;
	SSL_SESSION *sess;
	const unsigned char *p;

	p = (const unsigned char *)valbuf->buf;
	sess = d2i_SSL_SESSION(NULL, &p, valbuf->sz); /* increments p */
	if (!sess)
		return NULL;
	if (!ssl_session_is_valid(sess)) {
		SSL_SESSION_free(sess);
		return NULL;
	}
	if (copy)
		return sess;
	SSL_SESSION_free(sess);
	return ((cache_val_t)!NULL);
}
Esempio n. 17
0
File: ctx.c Progetto: Jimdo/stunnel
NOEXPORT SSL_SESSION *sess_get_cb(SSL *ssl,
        unsigned char *key, int key_len, int *do_copy) {
    unsigned char *val, *val_tmp=NULL;
    unsigned int val_len=0;
    SSL_SESSION *sess;

    *do_copy = 0; /* allow the session to be freed autmatically */
    cache_transfer(ssl->ctx, CACHE_CMD_GET, 0,
        key, key_len, NULL, 0, &val, &val_len);
    if(!val)
        return NULL;
    val_tmp=val;
    sess=d2i_SSL_SESSION(NULL,
#if OPENSSL_VERSION_NUMBER>=0x0090800fL
        (const unsigned char **)
#endif /* OpenSSL version >= 0.8.0 */
        &val_tmp, val_len);
    str_free(val);
    return sess;
}
Esempio n. 18
0
/* tls_decrypt_ticket attempts to decrypt a session ticket.
 *
 *   etick: points to the body of the session ticket extension.
 *   eticklen: the length of the session tickets extenion.
 *   sess_id: points at the session ID.
 *   sesslen: the length of the session ID.
 *   psess: (output) on return, if a ticket was decrypted, then this is set to
 *       point to the resulting session.
 *
 * Returns:
 *   -1: fatal error, either from parsing or decrypting the ticket.
 *    2: the ticket couldn't be decrypted.
 *    3: a ticket was successfully decrypted and *psess was set.
 *    4: same as 3, but the ticket needs to be renewed.
 */
static int
tls_decrypt_ticket(SSL *s, const unsigned char *etick, int eticklen,
    const unsigned char *sess_id, int sesslen, SSL_SESSION **psess)
{
	SSL_SESSION *sess;
	unsigned char *sdec;
	const unsigned char *p;
	int slen, mlen, renew_ticket = 0;
	unsigned char tick_hmac[EVP_MAX_MD_SIZE];
	HMAC_CTX hctx;
	EVP_CIPHER_CTX ctx;
	SSL_CTX *tctx = s->initial_ctx;

	/*
	 * The API guarantees EVP_MAX_IV_LENGTH bytes of space for
	 * the iv to tlsext_ticket_key_cb().  Since the total space
	 * required for a session cookie is never less than this,
	 * this check isn't too strict.  The exact check comes later.
	 */
	if (eticklen < 16 + EVP_MAX_IV_LENGTH)
		return 2;

	/* Initialize session ticket encryption and HMAC contexts */
	HMAC_CTX_init(&hctx);
	EVP_CIPHER_CTX_init(&ctx);
	if (tctx->internal->tlsext_ticket_key_cb) {
		unsigned char *nctick = (unsigned char *)etick;
		int rv = tctx->internal->tlsext_ticket_key_cb(s,
		    nctick, nctick + 16, &ctx, &hctx, 0);
		if (rv < 0) {
			HMAC_CTX_cleanup(&hctx);
			EVP_CIPHER_CTX_cleanup(&ctx);
			return -1;
		}
		if (rv == 0) {
			HMAC_CTX_cleanup(&hctx);
			EVP_CIPHER_CTX_cleanup(&ctx);
			return 2;
		}
		if (rv == 2)
			renew_ticket = 1;
	} else {
		/* Check key name matches */
		if (timingsafe_memcmp(etick,
		    tctx->internal->tlsext_tick_key_name, 16))
			return 2;
		HMAC_Init_ex(&hctx, tctx->internal->tlsext_tick_hmac_key,
		    16, tlsext_tick_md(), NULL);
		EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
		    tctx->internal->tlsext_tick_aes_key, etick + 16);
	}

	/*
	 * Attempt to process session ticket, first conduct sanity and
	 * integrity checks on ticket.
	 */
	mlen = HMAC_size(&hctx);
	if (mlen < 0) {
		HMAC_CTX_cleanup(&hctx);
		EVP_CIPHER_CTX_cleanup(&ctx);
		return -1;
	}

	/* Sanity check ticket length: must exceed keyname + IV + HMAC */
	if (eticklen <= 16 + EVP_CIPHER_CTX_iv_length(&ctx) + mlen) {
		HMAC_CTX_cleanup(&hctx);
		EVP_CIPHER_CTX_cleanup(&ctx);
		return 2;
	}
	eticklen -= mlen;

	/* Check HMAC of encrypted ticket */
	if (HMAC_Update(&hctx, etick, eticklen) <= 0 ||
	    HMAC_Final(&hctx, tick_hmac, NULL) <= 0) {
		HMAC_CTX_cleanup(&hctx);
		EVP_CIPHER_CTX_cleanup(&ctx);
		return -1;
	}

	HMAC_CTX_cleanup(&hctx);
	if (timingsafe_memcmp(tick_hmac, etick + eticklen, mlen)) {
		EVP_CIPHER_CTX_cleanup(&ctx);
		return 2;
	}

	/* Attempt to decrypt session data */
	/* Move p after IV to start of encrypted ticket, update length */
	p = etick + 16 + EVP_CIPHER_CTX_iv_length(&ctx);
	eticklen -= 16 + EVP_CIPHER_CTX_iv_length(&ctx);
	sdec = malloc(eticklen);
	if (sdec == NULL ||
	    EVP_DecryptUpdate(&ctx, sdec, &slen, p, eticklen) <= 0) {
		free(sdec);
		EVP_CIPHER_CTX_cleanup(&ctx);
		return -1;
	}
	if (EVP_DecryptFinal_ex(&ctx, sdec + slen, &mlen) <= 0) {
		free(sdec);
		EVP_CIPHER_CTX_cleanup(&ctx);
		return 2;
	}
	slen += mlen;
	EVP_CIPHER_CTX_cleanup(&ctx);
	p = sdec;

	sess = d2i_SSL_SESSION(NULL, &p, slen);
	free(sdec);
	if (sess) {
		/* The session ID, if non-empty, is used by some clients to
		 * detect that the ticket has been accepted. So we copy it to
		 * the session structure. If it is empty set length to zero
		 * as required by standard.
		 */
		if (sesslen)
			memcpy(sess->session_id, sess_id, sesslen);
		sess->session_id_length = sesslen;
		*psess = sess;
		if (renew_ticket)
			return 4;
		else
			return 3;
	}
	ERR_clear_error();
	/* For session parse failure, indicate that we need to send a new
	 * ticket. */
	return 2;
}
static ngx_int_t
ngx_stream_upstream_set_round_robin_peer_session(ngx_peer_connection_t *pc,
    void *data)
{
    ngx_stream_upstream_rr_peer_data_t  *rrp = data;

    ngx_int_t                        rc;
    ngx_ssl_session_t               *ssl_session;
    ngx_stream_upstream_rr_peer_t   *peer;
#if (NGX_STREAM_UPSTREAM_ZONE)
    int                              len;
#if OPENSSL_VERSION_NUMBER >= 0x0090707fL
    const
#endif
    u_char                          *p;
    ngx_stream_upstream_rr_peers_t  *peers;
    u_char                           buf[NGX_SSL_MAX_SESSION_SIZE];
#endif

    peer = rrp->current;

#if (NGX_STREAM_UPSTREAM_ZONE)
    peers = rrp->peers;

    if (peers->shpool) {
        ngx_stream_upstream_rr_peers_rlock(peers);
        ngx_stream_upstream_rr_peer_lock(peers, peer);

        if (peer->ssl_session == NULL) {
            ngx_stream_upstream_rr_peer_unlock(peers, peer);
            ngx_stream_upstream_rr_peers_unlock(peers);
            return NGX_OK;
        }

        len = peer->ssl_session_len;

        ngx_memcpy(buf, peer->ssl_session, len);

        ngx_stream_upstream_rr_peer_unlock(peers, peer);
        ngx_stream_upstream_rr_peers_unlock(peers);

        p = buf;
        ssl_session = d2i_SSL_SESSION(NULL, &p, len);

        rc = ngx_ssl_set_session(pc->connection, ssl_session);

        ngx_log_debug1(NGX_LOG_DEBUG_STREAM, pc->log, 0,
                       "set session: %p", ssl_session);

        ngx_ssl_free_session(ssl_session);

        return rc;
    }
#endif

    ssl_session = peer->ssl_session;

    rc = ngx_ssl_set_session(pc->connection, ssl_session);

    ngx_log_debug1(NGX_LOG_DEBUG_STREAM, pc->log, 0,
                   "set session: %p", ssl_session);

    return rc;
}
Esempio n. 20
0
int MAIN(int argc, char **argv)
	{
	SSL_SESSION *x=NULL;
	int ret=1,i,num,badops=0;
	BIO *out=NULL;
	int informat,outformat;
	char *infile=NULL,*outfile=NULL,*context=NULL;
	int cert=0,noout=0,text=0;
	char **pp;

	apps_startup();

	if (bio_err == NULL)
		if ((bio_err=BIO_new(BIO_s_file())) != NULL)
			BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);

	informat=FORMAT_PEM;
	outformat=FORMAT_PEM;

	argc--;
	argv++;
	num=0;
	while (argc >= 1)
		{
		if 	(strcmp(*argv,"-inform") == 0)
			{
			if (--argc < 1) goto bad;
			informat=str2fmt(*(++argv));
			}
		else if (strcmp(*argv,"-outform") == 0)
			{
			if (--argc < 1) goto bad;
			outformat=str2fmt(*(++argv));
			}
		else if (strcmp(*argv,"-in") == 0)
			{
			if (--argc < 1) goto bad;
			infile= *(++argv);
			}
		else if (strcmp(*argv,"-out") == 0)
			{
			if (--argc < 1) goto bad;
			outfile= *(++argv);
			}
		else if (strcmp(*argv,"-text") == 0)
			text= ++num;
		else if (strcmp(*argv,"-cert") == 0)
			cert= ++num;
		else if (strcmp(*argv,"-noout") == 0)
			noout= ++num;
		else if (strcmp(*argv,"-context") == 0)
		    {
		    if(--argc < 1) goto bad;
		    context=*++argv;
		    }
		else
			{
			BIO_printf(bio_err,"unknown option %s\n",*argv);
			badops=1;
			break;
			}
		argc--;
		argv++;
		}

	if (badops)
		{
bad:
		for (pp=sess_id_usage; (*pp != NULL); pp++)
			BIO_printf(bio_err,*pp);
		goto end;
		}

	ERR_load_crypto_strings();
	x=load_sess_id(infile,informat);
	if (x == NULL) { goto end; }

	if(context)
	    {
	    x->sid_ctx_length=strlen(context);
	    if(x->sid_ctx_length > SSL_MAX_SID_CTX_LENGTH)
		{
		BIO_printf(bio_err,"Context too long\n");
		goto end;
		}
	    memcpy(x->sid_ctx,context,x->sid_ctx_length);
	    }

#ifdef undef
	/* just testing for memory leaks :-) */
	{
	SSL_SESSION *s;
	char buf[1024*10],*p;
	int i;

	s=SSL_SESSION_new();

	p= &buf;
	i=i2d_SSL_SESSION(x,&p);
	p= &buf;
	d2i_SSL_SESSION(&s,&p,(long)i);
	p= &buf;
	d2i_SSL_SESSION(&s,&p,(long)i);
	p= &buf;
	d2i_SSL_SESSION(&s,&p,(long)i);
	SSL_SESSION_free(s);
	}
#endif

	if (!noout || text)
		{
		out=BIO_new(BIO_s_file());
		if (out == NULL)
			{
			ERR_print_errors(bio_err);
			goto end;
			}

		if (outfile == NULL)
			{
			BIO_set_fp(out,stdout,BIO_NOCLOSE);
#ifdef VMS
			{
			BIO *tmpbio = BIO_new(BIO_f_linebuffer());
			out = BIO_push(tmpbio, out);
			}
#endif
			}
		else
			{
			if (BIO_write_filename(out,outfile) <= 0)
				{
				perror(outfile);
				goto end;
				}
			}
		}

	if (text)
		{
		SSL_SESSION_print(out,x);

		if (cert)
			{
			if (x->peer == NULL)
				BIO_puts(out,"No certificate present\n");
			else
				X509_print(out,x->peer);
			}
		}

	if (!noout && !cert)
		{
		if 	(outformat == FORMAT_ASN1)
			i=(int)i2d_SSL_SESSION_bio(out,x);
		else if (outformat == FORMAT_PEM)
			i=PEM_write_bio_SSL_SESSION(out,x);
		else	{
			BIO_printf(bio_err,"bad output format specified for outfile\n");
			goto end;
			}
		if (!i) {
			BIO_printf(bio_err,"unable to write SSL_SESSION\n");
			goto end;
			}
		}
	else if (!noout && (x->peer != NULL)) /* just print the certificate */
		{
		if 	(outformat == FORMAT_ASN1)
			i=(int)i2d_X509_bio(out,x->peer);
		else if (outformat == FORMAT_PEM)
			i=PEM_write_bio_X509(out,x->peer);
		else	{
			BIO_printf(bio_err,"bad output format specified for outfile\n");
			goto end;
			}
		if (!i) {
			BIO_printf(bio_err,"unable to write X509\n");
			goto end;
			}
		}
	ret=0;
end:
	if (out != NULL) BIO_free_all(out);
	if (x != NULL) SSL_SESSION_free(x);
	EXIT(ret);
	}
Esempio n. 21
0
static int tls_decrypt_ticket(SSL *s, const unsigned char *etick, int eticklen,
				const unsigned char *sess_id, int sesslen,
				SSL_SESSION **psess)
	{
	SSL_SESSION *sess;
	unsigned char *sdec;
	const unsigned char *p;
	int slen, mlen, renew_ticket = 0;
	unsigned char tick_hmac[EVP_MAX_MD_SIZE];
	HMAC_CTX hctx;
	EVP_CIPHER_CTX ctx;
	SSL_CTX *tctx = s->initial_ctx;
	/* Need at least keyname + iv + some encrypted data */
	if (eticklen < 48)
		goto tickerr;
	/* Initialize session ticket encryption and HMAC contexts */
	HMAC_CTX_init(&hctx);
	EVP_CIPHER_CTX_init(&ctx);
	if (tctx->tlsext_ticket_key_cb)
		{
		unsigned char *nctick = (unsigned char *)etick;
		int rv = tctx->tlsext_ticket_key_cb(s, nctick, nctick + 16,
							&ctx, &hctx, 0);
		if (rv < 0)
			return -1;
		if (rv == 0)
			goto tickerr;
		if (rv == 2)
			renew_ticket = 1;
		}
	else
		{
		/* Check key name matches */
		if (memcmp(etick, tctx->tlsext_tick_key_name, 16))
			goto tickerr;
		HMAC_Init_ex(&hctx, tctx->tlsext_tick_hmac_key, 16,
					tlsext_tick_md(), NULL);
		EVP_DecryptInit_ex(&ctx, EVP_aes_128_cbc(), NULL,
				tctx->tlsext_tick_aes_key, etick + 16);
		}
	/* Attempt to process session ticket, first conduct sanity and
 	 * integrity checks on ticket.
 	 */
	mlen = HMAC_size(&hctx);
	eticklen -= mlen;
	/* Check HMAC of encrypted ticket */
	HMAC_Update(&hctx, etick, eticklen);
	HMAC_Final(&hctx, tick_hmac, NULL);
	HMAC_CTX_cleanup(&hctx);
	if (memcmp(tick_hmac, etick + eticklen, mlen))
		goto tickerr;
	/* Attempt to decrypt session data */
	/* Move p after IV to start of encrypted ticket, update length */
	p = etick + 16 + EVP_CIPHER_CTX_iv_length(&ctx);
	eticklen -= 16 + EVP_CIPHER_CTX_iv_length(&ctx);
	sdec = OPENSSL_malloc(eticklen);
	if (!sdec)
		{
		EVP_CIPHER_CTX_cleanup(&ctx);
		return -1;
		}
	EVP_DecryptUpdate(&ctx, sdec, &slen, p, eticklen);
	if (EVP_DecryptFinal(&ctx, sdec + slen, &mlen) <= 0)
		goto tickerr;
	slen += mlen;
	EVP_CIPHER_CTX_cleanup(&ctx);
	p = sdec;
		
	sess = d2i_SSL_SESSION(NULL, &p, slen);
	OPENSSL_free(sdec);
	if (sess)
		{
		/* The session ID if non-empty is used by some clients to
 		 * detect that the ticket has been accepted. So we copy it to
 		 * the session structure. If it is empty set length to zero
 		 * as required by standard.
 		 */
		if (sesslen)
			memcpy(sess->session_id, sess_id, sesslen);
		sess->session_id_length = sesslen;
		*psess = sess;
		s->tlsext_ticket_expected = renew_ticket;
		return 1;
		}
	/* If session decrypt failure indicate a cache miss and set state to
 	 * send a new ticket
 	 */
	tickerr:	
	s->tlsext_ticket_expected = 1;
	return 0;
	}