Ticket #120: nginx-rfc5077.patch
| File nginx-rfc5077.patch, 30.5 KB (added by , 14 years ago) |
|---|
-
src/core/ngx_string.c
diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c index 3b392f7..a6f6a27 100644
a b ngx_pstrdup(ngx_pool_t *pool, ngx_str_t *src) 79 79 * %[0][width][u][x|X]L int64_t/uint64_t 80 80 * %[0][width|m][u][x|X]A ngx_atomic_int_t/ngx_atomic_uint_t 81 81 * %[0][width][.width]f double, max valid number fits to %18.15f 82 * %[x|X]*s length and string 82 83 * %P ngx_pid_t 83 84 * %M ngx_msec_t 84 85 * %r rlim_t … … ngx_pstrdup(ngx_pool_t *pool, ngx_str_t *src) 86 87 * %V ngx_str_t * 87 88 * %v ngx_variable_value_t * 88 89 * %s null-terminated string 89 * %*s length and string90 90 * %Z '\0' 91 91 * %N '\n' 92 92 * %c char … … ngx_slprintf(u_char *buf, u_char *last, const char *fmt, ...) 141 141 } 142 142 143 143 144 static u_char ngx_hex[] = "0123456789abcdef"; 145 static u_char ngx_HEX[] = "0123456789ABCDEF"; 146 144 147 u_char * 145 148 ngx_vslprintf(u_char *buf, u_char *last, const char *fmt, va_list args) 146 149 { 147 u_char *p, zero ;150 u_char *p, zero, *hex_p; 148 151 int d; 149 152 double f; 150 153 size_t len, slen; … … ngx_vslprintf(u_char *buf, u_char *last, const char *fmt, va_list args) 250 253 case 's': 251 254 p = va_arg(args, u_char *); 252 255 253 if (slen == (size_t) -1) { 254 while (*p && buf < last) { 255 *buf++ = *p++; 256 if (hex == 0) { 257 if (slen == (size_t) -1) { 258 while (*p && buf < last) { 259 *buf++ = *p++; 260 } 261 } else { 262 len = ngx_min(((size_t) (last - buf)), slen); 263 buf = ngx_cpymem(buf, p, len); 256 264 } 257 258 265 } else { 259 len = ngx_min(((size_t) (last - buf)), slen); 260 buf = ngx_cpymem(buf, p, len); 266 if ( hex == 1 ) { 267 hex_p = ngx_hex; 268 } else { 269 hex_p = ngx_HEX; 270 } 271 while (buf < (last-1)) { 272 if ( slen == (size_t) -1) { 273 if (!*p) break; 274 } else { 275 if ( slen == 0 ) { 276 break; 277 } else { 278 --slen; 279 } 280 } 281 *buf++ = hex_p[ ((uint32_t) *p & 0xf0) >> 4]; 282 *buf++ = hex_p[ ((uint32_t) *p) & 0xf]; 283 ++p; 284 } 261 285 } 262 286 263 287 fmt++; … … ngx_sprintf_num(u_char *buf, u_char *last, uint64_t ui64, u_char zero, 479 503 */ 480 504 size_t len; 481 505 uint32_t ui32; 482 static u_char hex[] = "0123456789abcdef";483 static u_char HEX[] = "0123456789ABCDEF";484 506 485 507 p = temp + NGX_INT64_LEN; 486 508 … … ngx_sprintf_num(u_char *buf, u_char *last, uint64_t ui64, u_char zero, 520 542 do { 521 543 522 544 /* the "(uint32_t)" cast disables the BCC's warning */ 523 *--p = hex[(uint32_t) (ui64 & 0xf)];545 *--p = ngx_hex[(uint32_t) (ui64 & 0xf)]; 524 546 525 547 } while (ui64 >>= 4); 526 548 … … ngx_sprintf_num(u_char *buf, u_char *last, uint64_t ui64, u_char zero, 529 551 do { 530 552 531 553 /* the "(uint32_t)" cast disables the BCC's warning */ 532 *--p = HEX[(uint32_t) (ui64 & 0xf)];554 *--p = ngx_HEX[(uint32_t) (ui64 & 0xf)]; 533 555 534 556 } while (ui64 >>= 4); 535 557 } -
src/event/ngx_event_openssl.c
diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c index 4356a05..073ef22 100644
a b static void ngx_ssl_connection_error(ngx_connection_t *c, int sslerr, 27 27 ngx_err_t err, char *text); 28 28 static void ngx_ssl_clear_error(ngx_log_t *log); 29 29 30 ngx_int_t ngx_ssl_ session_cache_init(ngx_shm_zone_t *shm_zone, void *data);30 ngx_int_t ngx_ssl_cache_init(ngx_shm_zone_t *shm_zone, void *data); 31 31 static int ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, 32 32 ngx_ssl_session_t *sess); 33 33 static ngx_ssl_session_t *ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn, … … static void ngx_ssl_expire_sessions(ngx_ssl_session_cache_t *cache, 38 38 static void ngx_ssl_session_rbtree_insert_value(ngx_rbtree_node_t *temp, 39 39 ngx_rbtree_node_t *node, ngx_rbtree_node_t *sentinel); 40 40 41 static int ngx_ssl_tlsext_ticket_key_cb(SSL *s, unsigned char *key_name, 42 unsigned char *iv, EVP_CIPHER_CTX *ctx, HMAC_CTX *hctx, int enc); 43 static ngx_int_t ngx_ssl_ticket_cache_init(ngx_ssl_ticket_cache_t *cache, ngx_log_t *log); 44 static ngx_int_t ngx_ssl_ticket_new(ngx_ssl_ticket_cache_t *cache, unsigned i, long expire); 45 41 46 static void *ngx_openssl_create_conf(ngx_cycle_t *cycle); 42 47 static char *ngx_openssl_engine(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); 43 48 static void ngx_openssl_exit(ngx_cycle_t *cycle); … … ngx_module_t ngx_openssl_module = { 80 85 81 86 82 87 int ngx_ssl_connection_index; 83 int ngx_ssl_server_conf_index;84 88 int ngx_ssl_session_cache_index; 89 int ngx_ssl_ticket_timeout_index; 85 90 86 91 87 92 ngx_int_t … … ngx_ssl_init(ngx_log_t *log) 115 120 ngx_ssl_connection_index = SSL_get_ex_new_index(0, NULL, NULL, NULL, NULL); 116 121 117 122 if (ngx_ssl_connection_index == -1) { 118 ngx_ssl_error(NGX_LOG_ALERT, log, 0, "SSL_get_ex_new_index() failed");119 return NGX_ERROR;120 }121 122 ngx_ssl_server_conf_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL,123 NULL);124 if (ngx_ssl_server_conf_index == -1) {125 123 ngx_ssl_error(NGX_LOG_ALERT, log, 0, 126 "SSL_CTX_get_ex_new_index() f ailed");124 "SSL_CTX_get_ex_new_index() for ssl_connection failed"); 127 125 return NGX_ERROR; 128 126 } 129 127 … … ngx_ssl_init(ngx_log_t *log) 131 129 NULL); 132 130 if (ngx_ssl_session_cache_index == -1) { 133 131 ngx_ssl_error(NGX_LOG_ALERT, log, 0, 134 "SSL_CTX_get_ex_new_index() f ailed");132 "SSL_CTX_get_ex_new_index() for session cache failed"); 135 133 return NGX_ERROR; 136 134 } 137 135 136 ngx_ssl_ticket_timeout_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, 137 NULL); 138 if (ngx_ssl_ticket_timeout_index == -1) { 139 ngx_ssl_error(NGX_LOG_ALERT, log, 0, 140 "SSL_CTX_get_ex_new_index() for ticket_timeout failed"); 141 return NGX_ERROR; 142 } 138 143 return NGX_OK; 139 144 } 140 145 … … ngx_ssl_create(ngx_ssl_t *ssl, ngx_uint_t protocols, void *data) 149 154 return NGX_ERROR; 150 155 } 151 156 152 if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_server_conf_index, data) == 0) {153 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0,154 "SSL_CTX_set_ex_data() failed");155 return NGX_ERROR;156 }157 158 157 /* client side options */ 159 158 160 159 SSL_CTX_set_options(ssl->ctx, SSL_OP_MICROSOFT_SESS_ID_BUG); … … ngx_ssl_error(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, char *fmt, ...) 1513 1512 1514 1513 ngx_int_t 1515 1514 ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx, 1516 ssize_t builtin_session_cache, ngx_shm_zone_t *shm_zone, time_t timeout) 1515 ssize_t builtin_session_cache, ngx_shm_zone_t *shm_zone, 1516 time_t session_timeout, time_t *ticket_timeout) 1517 1517 { 1518 1518 long cache_mode; 1519 1519 … … ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx, 1562 1562 } 1563 1563 } 1564 1564 1565 SSL_CTX_set_timeout(ssl->ctx, (long) timeout);1565 SSL_CTX_set_timeout(ssl->ctx, (long) session_timeout); 1566 1566 1567 1567 if (shm_zone) { 1568 1568 SSL_CTX_sess_set_new_cb(ssl->ctx, ngx_ssl_new_session); 1569 1569 SSL_CTX_sess_set_get_cb(ssl->ctx, ngx_ssl_get_cached_session); 1570 1570 SSL_CTX_sess_set_remove_cb(ssl->ctx, ngx_ssl_remove_session); 1571 1571 1572 SSL_CTX_set_tlsext_ticket_key_cb(ssl->ctx, ngx_ssl_tlsext_ticket_key_cb); 1573 1574 if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_ticket_timeout_index, 1575 ticket_timeout) == 0) 1576 { 1577 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, 1578 "SSL_CTX_set_ex_data() for ticket timeout failed"); 1579 return NGX_ERROR; 1580 } 1581 1572 1582 if (SSL_CTX_set_ex_data(ssl->ctx, ngx_ssl_session_cache_index, shm_zone) 1573 1583 == 0) 1574 1584 { 1575 1585 ngx_ssl_error(NGX_LOG_EMERG, ssl->log, 0, 1576 "SSL_CTX_set_ex_data() f ailed");1586 "SSL_CTX_set_ex_data() for session cache failed"); 1577 1587 return NGX_ERROR; 1578 1588 } 1579 1589 } … … ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx, 1583 1593 1584 1594 1585 1595 ngx_int_t 1586 ngx_ssl_ session_cache_init(ngx_shm_zone_t *shm_zone, void *data)1596 ngx_ssl_cache_init(ngx_shm_zone_t *shm_zone, void *data) 1587 1597 { 1588 1598 size_t len; 1589 1599 ngx_slab_pool_t *shpool; 1590 ngx_ssl_ session_cache_t*cache;1600 ngx_ssl_cache_t *cache; 1591 1601 1592 1602 if (data) { 1593 1603 shm_zone->data = data; … … ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data) 1601 1611 1602 1612 shpool = (ngx_slab_pool_t *) shm_zone->shm.addr; 1603 1613 1604 cache = ngx_slab_alloc(shpool, sizeof(ngx_ssl_ session_cache_t));1614 cache = ngx_slab_alloc(shpool, sizeof(ngx_ssl_cache_t)); 1605 1615 if (cache == NULL) { 1606 1616 return NGX_ERROR; 1607 1617 } … … ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data) 1609 1619 shpool->data = cache; 1610 1620 shm_zone->data = cache; 1611 1621 1612 ngx_rbtree_init(&cache->session _rbtree, &cache->sentinel,1622 ngx_rbtree_init(&cache->session.session_rbtree, &cache->session.sentinel, 1613 1623 ngx_ssl_session_rbtree_insert_value); 1614 1624 1615 ngx_queue_init(&cache-> expire_queue);1625 ngx_queue_init(&cache->session.expire_queue); 1616 1626 1617 len = sizeof(" in SSL s ession shared cache \"\"") + shm_zone->shm.name.len;1627 len = sizeof(" in SSL shared cache \"\"") + shm_zone->shm.name.len; 1618 1628 1619 1629 shpool->log_ctx = ngx_slab_alloc(shpool, len); 1620 1630 if (shpool->log_ctx == NULL) { 1621 1631 return NGX_ERROR; 1622 1632 } 1623 1633 1624 ngx_sprintf(shpool->log_ctx, " in SSL s ession shared cache \"%V\"%Z",1634 ngx_sprintf(shpool->log_ctx, " in SSL shared cache \"%V\"%Z", 1625 1635 &shm_zone->shm.name); 1626 1636 1637 ngx_ssl_ticket_cache_init(&cache->ticket, shm_zone->shm.log); 1638 1639 return NGX_OK; 1640 } 1641 1642 /* ssl tickets are RFC5077 tickets where the server 1643 * doesn't maintain a session crypto state for each client 1644 * Like session IDs it provides a mechanism for the client 1645 * to short cut the cryptographic exchange. It does this by 1646 * encrypting the crypto state information in the ticket 1647 * and providing it to the client. 1648 * 1649 * The server size cyptographic parameters that encrypt the 1650 * session expire for the same time as the session cache. 1651 * They are however renewed in 1/2 that time so clients can 1652 * progress to the new state without doing a full cryptographic 1653 * exchange. See note below about poor client support. 1654 */ 1655 1656 static ngx_int_t 1657 ngx_ssl_ticket_cache_init(ngx_ssl_ticket_cache_t *cache, ngx_log_t *log) 1658 { 1659 int i; 1660 1661 for (i = 0; i< NGX_SSL_ACTIVE_TICKETS; i++) { 1662 cache->keystore[i].keys.expire = (unsigned long) -1; 1663 } 1664 cache->keystore_i = 0; 1665 #if (NGX_THREADS) 1666 cache->keyrefresh = ngx_mutex_init(log, 0); 1667 if (cache->keyrefresh == NULL) { 1668 ngx_log_error(NGX_LOG_ERR, log, 0, 1669 "key refresh mutex initialisation failure"); 1670 return NGX_ERROR; 1671 } 1672 #endif 1673 return NGX_OK; 1674 } 1675 1676 1677 #define NGX_RENEW_SSL_TICKET 1678 /* Suspect that some clients aren't handling renewals properly 1679 * despite being in rfc5077 3.3 paragraph 2. 1680 * Tested clients: 1681 * nss 3.13.5 1682 * gnutls 2.12.17 1683 * openssl 1.0.0j 1684 * 1685 * returns 0 if expired, 1 if early and valid, 2 if renew */ 1686 static ngx_int_t ngx_ssl_ticket_valid(time_t now, time_t ref, long expire) { 1687 #ifdef NGX_RENEW_SSL_TICKET 1688 long renew = expire / 2; 1689 #endif 1690 if ( now <= ref ) { 1691 #ifdef NGX_RENEW_SSL_TICKET 1692 if ( now < (ref - renew) ) { 1693 return 1; 1694 } else { 1695 return 2; 1696 } 1697 #else 1698 return 1; 1699 #endif 1700 } else { 1701 return 0; 1702 } 1703 } 1704 1705 static ngx_int_t 1706 ngx_ssl_ticket_new(ngx_ssl_ticket_cache_t *cache,unsigned i, long expire) 1707 { 1708 ngx_ssl_ticket_id_t *keys = &cache->keystore[i]; 1709 if ((RAND_bytes(keys->keys.hmac_key, 16) <= 0) 1710 || (RAND_bytes(keys->keys.aes_key, 16) <= 0) 1711 || (RAND_pseudo_bytes(keys->key_name, 16) <= 0)) 1712 return NGX_ERROR; 1713 keys->keys.expire = ngx_time() + expire; 1627 1714 return NGX_OK; 1628 1715 } 1629 1716 1630 1717 1718 static int 1719 ngx_ssl_tlsext_ticket_key_create(ngx_ssl_ticket_cache_t *cache, ngx_log_t *log, 1720 unsigned char *key_name, unsigned char *iv, EVP_CIPHER_CTX *ctx, 1721 HMAC_CTX *hctx, long expiretime) 1722 { 1723 time_t t; 1724 unsigned newi; 1725 ngx_ssl_ticket_id_t *k; 1726 1727 t = ngx_time(); 1728 1729 /* create new session */ 1730 if (RAND_bytes(iv, EVP_MAX_IV_LENGTH) <= 0) { 1731 ngx_log_error(NGX_LOG_WARN, log, 0, 1732 "RAND_bytes entropy empty on iv initialisation"); 1733 return -1; 1734 } 1735 ngx_log_debug5(NGX_LOG_DEBUG_EVENT, log, 0, 1736 "New iv %*Xs time %T current key expire %T expire interval %l", 1737 (size_t) EVP_MAX_IV_LENGTH, iv, 1738 t, cache->keystore[cache->keystore_i].keys.expire, 1739 expiretime); 1740 switch ( ngx_ssl_ticket_valid(t, cache->keystore[cache->keystore_i].keys.expire, 1741 expiretime)) { 1742 case 1: 1743 ngx_log_error(NGX_LOG_WARN, log, 0, 1744 "current ticket sufficient"); 1745 break; 1746 case 2: 1747 ngx_log_debug(NGX_LOG_DEBUG_EVENT, log, 0, 1748 "session ticket key valid but in renew period - use new key"); 1749 /* time for a new key */ 1750 #if (NGX_THREADS) 1751 ngx_shmtx_lock(cache->keyrefresh); 1752 #endif 1753 /* check the next entry is expired inside the mutex to avoid a race 1754 * condition if another worker already updated this */ 1755 newi = ( cache->keystore_i + 1) % NGX_SSL_ACTIVE_TICKETS; 1756 if ( ngx_ssl_ticket_valid(t, cache->keystore[newi].keys.expire, 1757 expiretime) == 0) { 1758 if (ngx_ssl_ticket_new(cache,newi,expiretime) == NGX_OK) { 1759 ngx_log_error(NGX_LOG_INFO, log, 0, 1760 "New ssl session ticket generated"); 1761 } else { 1762 /* insufficent randomness */ 1763 ngx_log_error(NGX_LOG_WARN, log, 0, 1764 "RAND_bytes entropy empty on new key material"); 1765 #if (NGX_THREADS) 1766 ngx_shmtx_unlock(cache->keyrefresh); 1767 #endif 1768 return -1; 1769 } 1770 cache->keystore_i = newi; 1771 ngx_log_debug7(NGX_LOG_DEBUG_EVENT, log, 0, 1772 "New key/hmac for SSL session ticket key %d name %*Xs" 1773 "aes_key %*Xs hmac_key %*Xs", 1774 newi, 1775 (size_t)16, cache->keystore[newi].key_name, 1776 (size_t)16, cache->keystore[newi].keys.aes_key, 1777 (size_t)16, cache->keystore[newi].keys.hmac_key); 1778 } else { 1779 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0, "Was tasked to SSL" 1780 "session renew ticket %d but it wasn't expired. Assume another" 1781 "thread/process fixed it for us", newi); 1782 } 1783 #if (NGX_THREADS) 1784 ngx_shmtx_unlock(cache->keyrefresh); 1785 #endif 1786 break; 1787 case 0: 1788 /* primary key expired */ 1789 ngx_log_debug(NGX_LOG_DEBUG_EVENT, log, 0, 1790 "SSL session ticket current key expired - generating"); 1791 #if (NGX_THREADS) 1792 ngx_shmtx_lock(cache->keyrefresh); 1793 #endif 1794 /* race condition prevention inside mutex */ 1795 if ( ngx_ssl_ticket_valid(t, 1796 cache->keystore[cache->keystore_i].keys.expire, expiretime) == 0) { 1797 if (ngx_ssl_ticket_new(cache,cache->keystore_i, expiretime) 1798 == NGX_OK) { 1799 ngx_log_error(NGX_LOG_INFO, log, 0, 1800 "New ssl session ticket generated"); 1801 } else { 1802 /* insufficent randomness */ 1803 ngx_log_error(NGX_LOG_WARN, log, 0, 1804 "RAND_bytes entropy empty on new key material"); 1805 #if (NGX_THREADS) 1806 ngx_shmtx_unlock(&(cache->keyrefresh)); 1807 #endif 1808 return -1; 1809 } 1810 } else { 1811 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0, 1812 "SSL session ticket was to renew current ticket %d but it wasn't" 1813 " expired. Assume another thread/process fixed it for us" 1814 , cache->keystore_i); 1815 } 1816 newi = cache->keystore_i; 1817 #if (NGX_THREADS) 1818 ngx_shmtx_unlock(&(cache->keyrefresh)); 1819 #endif 1820 ngx_log_debug7(NGX_LOG_DEBUG_EVENT, log, 0, 1821 "New key/hmac for SSL session ticket key %d name %*Xs aes_key %*Xs" 1822 " hmac_key %*Xs", 1823 newi, 1824 (size_t) 16, cache->keystore[newi].key_name, 1825 (size_t) 16, cache->keystore[newi].keys.aes_key, 1826 (size_t) 16, cache->keystore[newi].keys.hmac_key); 1827 } 1828 k = &cache->keystore[cache->keystore_i]; 1829 ngx_memcpy(key_name, k->key_name, 16); 1830 1831 EVP_EncryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, k->keys.aes_key, iv); 1832 HMAC_Init_ex(hctx, k->keys.hmac_key, 16, EVP_sha256(), NULL); 1833 ngx_log_debug7(NGX_LOG_DEBUG_EVENT, log, 0, 1834 "New SSL session ticket %d with name %*Xs aes_key %*Xs hmac_key %*Xs", 1835 cache->keystore_i, 1836 (size_t) 16, k->key_name, 1837 (size_t) 16, k->keys.aes_key, 1838 (size_t) 16, k->keys.hmac_key); 1839 return 1; 1840 } 1841 1842 /* tip copied off the Apache httpd source - assumed tlsext_tick_md didn't exist 1843 * at some version of openssl */ 1844 #ifndef tlsext_tick_md 1845 #ifdef OPENSSL_NO_SHA256 1846 #define tlsext_tick_md EVP_sha1 1847 #else 1848 #define tlsext_tick_md EVP_sha256 1849 #endif 1850 #endif 1851 1852 static int 1853 ngx_ssl_tlsext_ticket_key_cb(ngx_ssl_conn_t *s, unsigned char *key_name, 1854 unsigned char *iv, EVP_CIPHER_CTX *ctx, HMAC_CTX *hctx, int enc) 1855 { 1856 SSL_CTX *ssl_ctx; 1857 ngx_shm_zone_t *shm_zone; 1858 ngx_ssl_cache_t *bigcache; 1859 ngx_ssl_ticket_cache_t *cache; 1860 ngx_connection_t *c; 1861 ngx_log_t *log; 1862 time_t t; 1863 ngx_ssl_ticket_keys_t *keys; 1864 unsigned a; 1865 unsigned i; 1866 int cmp; 1867 int renew; 1868 long expiretime; 1869 1870 ssl_ctx = SSL_get_SSL_CTX(s); 1871 shm_zone = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_session_cache_index); 1872 expiretime = *((long *) SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_ticket_timeout_index)); 1873 bigcache = shm_zone->data; 1874 cache = &bigcache->ticket; 1875 1876 c = ngx_ssl_get_connection(s); 1877 log = c->log; 1878 t = ngx_time(); 1879 1880 ngx_log_debug5(NGX_LOG_DEBUG_EVENT, log, 0, 1881 "tlsext_ticket_key_cb (in): key_name: %*Xs iv: %*Xs enc %d", 1882 (size_t) 16, key_name, 1883 (size_t) EVP_MAX_IV_LENGTH, iv, 1884 enc); 1885 if (enc) { 1886 return ngx_ssl_tlsext_ticket_key_create(cache, log, key_name, iv, ctx, 1887 hctx,expiretime); 1888 } else { 1889 /* retrieve session */ 1890 a = 0; 1891 cmp = -1; 1892 for (i = a = cache->keystore_i; 1893 i < NGX_SSL_ACTIVE_TICKETS && 1894 (cmp = ngx_memcmp(key_name, cache->keystore[a].key_name,16)!=0); 1895 ++i, a = (a + 1) % NGX_SSL_ACTIVE_TICKETS); 1896 if (cmp == 0) { 1897 keys = &cache->keystore[a].keys; 1898 } else { 1899 ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0, "SSL session ticket key " 1900 "%*Xs not found", (size_t) 16, key_name); 1901 return 0; 1902 } 1903 renew = ngx_ssl_ticket_valid(t, cache->keystore[a].keys.expire, 1904 expiretime); 1905 if (renew == 0) { 1906 ngx_log_debug3(NGX_LOG_DEBUG_EVENT, log, 0, "retreiving key %d " 1907 "expired %T < now %T", a, keys->expire, t); 1908 return 0; 1909 } 1910 1911 HMAC_Init_ex(hctx, keys->hmac_key, 16, tlsext_tick_md(), NULL); 1912 EVP_DecryptInit_ex(ctx, EVP_aes_128_cbc(), NULL, keys->aes_key, iv); 1913 ngx_log_debug8(NGX_LOG_DEBUG_EVENT, log, 0, 1914 "Resumed SSL session ticket %d with iv %*Xs aes_key %*Xs " 1915 "hmac_key %*Xs renew %s", 1916 a, 1917 (size_t) 16, iv, 1918 (size_t) 16, keys->aes_key, 1919 (size_t) 16, keys->hmac_key, 1920 ((renew == 2) ? "yes" : "no")); 1921 if (renew == 2) { 1922 /* this sesssion will get a new ticket. This is handled in the ssl 1923 * library and will call this function again with a enc=0 */ 1924 ngx_log_debug5(NGX_LOG_DEBUG_EVENT, log, 0, 1925 "tlsext_ticket_key_cb (out): key_name: %*Xs iv: %*Xs" 1926 " enc %d ret 2", 1927 (size_t) 16, key_name, 1928 (size_t) EVP_MAX_IV_LENGTH, iv, 1929 enc); 1930 return 2; 1931 } 1932 } 1933 ngx_log_debug5(NGX_LOG_DEBUG_EVENT, log, 0, 1934 "tlsext_ticket_key_cb (out): key_name: %*Xs iv: %*Xs enc %d - ret 1", 1935 (size_t) 16, key_name, 1936 (size_t) EVP_MAX_IV_LENGTH, iv, 1937 enc); 1938 return 1; 1939 } 1940 1941 1942 1943 1944 1631 1945 /* 1632 1946 * The length of the session id is 16 bytes for SSLv2 sessions and 1633 1947 * between 1 and 32 bytes for SSLv3/TLSv1, typically 32 bytes. … … ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess) 1661 1975 1662 1976 len = i2d_SSL_SESSION(sess, NULL); 1663 1977 1978 1979 /* This isn't called if a session ticket is created 1980 * see rfc5077 3.4 1981 */ 1982 1664 1983 /* do not cache too big session */ 1665 1984 1666 1985 if (len > (int) NGX_SSL_MAX_SESSION_SIZE) { … … ngx_ssl_new_session(ngx_ssl_conn_t *ssl_conn, ngx_ssl_session_t *sess) 1675 1994 ssl_ctx = SSL_get_SSL_CTX(ssl_conn); 1676 1995 shm_zone = SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_session_cache_index); 1677 1996 1678 cache = shm_zone->data;1997 cache = &((ngx_ssl_cache_t *) shm_zone->data)->session; 1679 1998 shpool = (ngx_slab_pool_t *) shm_zone->shm.addr; 1680 1999 1681 2000 ngx_shmtx_lock(&shpool->mutex); … … ngx_ssl_get_cached_session(ngx_ssl_conn_t *ssl_conn, u_char *id, int len, 1796 2115 shm_zone = SSL_CTX_get_ex_data(SSL_get_SSL_CTX(ssl_conn), 1797 2116 ngx_ssl_session_cache_index); 1798 2117 1799 cache = shm_zone->data;2118 cache = &((ngx_ssl_cache_t *) shm_zone->data)->session; 1800 2119 1801 2120 sess = NULL; 1802 2121 … … ngx_ssl_remove_session(SSL_CTX *ssl, ngx_ssl_session_t *sess) 1892 2211 return; 1893 2212 } 1894 2213 1895 cache = shm_zone->data;2214 cache = &((ngx_ssl_cache_t *) shm_zone->data)->session; 1896 2215 1897 2216 id = sess->session_id; 1898 2217 len = (size_t) sess->session_id_length; -
src/event/ngx_event_openssl.h
diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h index cd6d885..8850459 100644
a b typedef struct { 81 81 } ngx_ssl_session_cache_t; 82 82 83 83 84 /* RFC 5077 */ 85 typedef struct { 86 u_char hmac_key[16]; 87 u_char aes_key[16]; 88 time_t expire; 89 } ngx_ssl_ticket_keys_t; 90 91 92 typedef struct { 93 u_char key_name[16]; 94 ngx_ssl_ticket_keys_t keys; 95 } ngx_ssl_ticket_id_t; 96 97 98 #define NGX_SSL_ACTIVE_TICKETS 2 99 typedef struct { 100 volatile unsigned keystore_i; 101 ngx_ssl_ticket_id_t keystore[NGX_SSL_ACTIVE_TICKETS]; 102 #if (NGX_THREADS) 103 ngx_shmtx_t *keyrefresh; 104 #endif 105 } ngx_ssl_ticket_cache_t; 106 107 108 typedef struct { 109 ngx_ssl_session_cache_t session; 110 ngx_ssl_ticket_cache_t ticket; 111 } ngx_ssl_cache_t; 112 84 113 85 114 #define NGX_SSL_SSLv2 0x0002 86 115 #define NGX_SSL_SSLv3 0x0004 … … RSA *ngx_ssl_rsa512_key_callback(SSL *ssl, int is_export, int key_length); 106 135 ngx_int_t ngx_ssl_dhparam(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *file); 107 136 ngx_int_t ngx_ssl_ecdh_curve(ngx_conf_t *cf, ngx_ssl_t *ssl, ngx_str_t *name); 108 137 ngx_int_t ngx_ssl_session_cache(ngx_ssl_t *ssl, ngx_str_t *sess_ctx, 109 ssize_t builtin_session_cache, ngx_shm_zone_t *shm_zone, time_t timeout); 110 ngx_int_t ngx_ssl_session_cache_init(ngx_shm_zone_t *shm_zone, void *data); 138 ssize_t builtin_session_cache, ngx_shm_zone_t *shm_zone, 139 time_t session_timeout, long *ticket_timeout); 140 ngx_int_t ngx_ssl_cache_init(ngx_shm_zone_t *shm_zone, void *data); 111 141 ngx_int_t ngx_ssl_create_connection(ngx_ssl_t *ssl, ngx_connection_t *c, 112 142 ngx_uint_t flags); 113 143 … … ngx_int_t ngx_ssl_set_session(ngx_connection_t *c, ngx_ssl_session_t *session); 117 147 #define ngx_ssl_free_session SSL_SESSION_free 118 148 #define ngx_ssl_get_connection(ssl_conn) \ 119 149 SSL_get_ex_data(ssl_conn, ngx_ssl_connection_index) 120 #define ngx_ssl_get_server_conf(ssl_ctx) \121 SSL_CTX_get_ex_data(ssl_ctx, ngx_ssl_server_conf_index)122 150 123 151 124 152 ngx_int_t ngx_ssl_get_protocol(ngx_connection_t *c, ngx_pool_t *pool, … … void ngx_ssl_cleanup_ctx(void *data); 155 183 156 184 157 185 extern int ngx_ssl_connection_index; 158 extern int ngx_ssl_server_conf_index;159 186 extern int ngx_ssl_session_cache_index; 160 187 161 188 -
src/http/modules/ngx_http_ssl_module.c
diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c index d759489..2be0988 100644
a b static ngx_command_t ngx_http_ssl_commands[] = { 145 145 offsetof(ngx_http_ssl_srv_conf_t, session_timeout), 146 146 NULL }, 147 147 148 { ngx_string("ssl_ticket_timeout"), 149 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, 150 ngx_conf_set_sec_slot, 151 NGX_HTTP_SRV_CONF_OFFSET, 152 offsetof(ngx_http_ssl_srv_conf_t, ticket_timeout), 153 NULL }, 154 148 155 { ngx_string("ssl_crl"), 149 156 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_CONF_TAKE1, 150 157 ngx_conf_set_str_slot, … … ngx_http_ssl_create_srv_conf(ngx_conf_t *cf) 336 343 sscf->verify_depth = NGX_CONF_UNSET_UINT; 337 344 sscf->builtin_session_cache = NGX_CONF_UNSET; 338 345 sscf->session_timeout = NGX_CONF_UNSET; 346 sscf->ticket_timeout = NGX_CONF_UNSET; 339 347 340 348 return sscf; 341 349 } … … ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) 363 371 ngx_conf_merge_value(conf->session_timeout, 364 372 prev->session_timeout, 300); 365 373 374 ngx_conf_merge_value(conf->ticket_timeout, 375 prev->ticket_timeout, 60*60*24*7); /* 1 week */ 376 366 377 ngx_conf_merge_value(conf->prefer_server_ciphers, 367 378 prev->prefer_server_ciphers, 0); 368 379 … … ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child) 509 520 510 521 if (ngx_ssl_session_cache(&conf->ssl, &ngx_http_ssl_sess_id_ctx, 511 522 conf->builtin_session_cache, 512 conf->shm_zone, conf->session_timeout) 523 conf->shm_zone, conf->session_timeout, 524 &conf->ticket_timeout) 513 525 != NGX_OK) 514 526 { 515 527 return NGX_CONF_ERROR; … … ngx_http_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 629 641 return NGX_CONF_ERROR; 630 642 } 631 643 632 sscf->shm_zone->init = ngx_ssl_ session_cache_init;644 sscf->shm_zone->init = ngx_ssl_cache_init; 633 645 634 646 continue; 635 647 } -
src/http/modules/ngx_http_ssl_module.h
diff --git a/src/http/modules/ngx_http_ssl_module.h b/src/http/modules/ngx_http_ssl_module.h index 58659ab..3fe79f0 100644
a b typedef struct { 29 29 ssize_t builtin_session_cache; 30 30 31 31 time_t session_timeout; 32 long ticket_timeout; 32 33 33 34 ngx_str_t certificate; 34 35 ngx_str_t certificate_key; -
src/mail/ngx_mail_ssl_module.c
diff --git a/src/mail/ngx_mail_ssl_module.c b/src/mail/ngx_mail_ssl_module.c index dd6f2ac..93a4070 100644
a b static ngx_command_t ngx_mail_ssl_commands[] = { 123 123 offsetof(ngx_mail_ssl_conf_t, session_timeout), 124 124 NULL }, 125 125 126 { ngx_string("ssl_ticket_session_timeout"), 127 NGX_MAIL_MAIN_CONF|NGX_MAIL_SRV_CONF|NGX_CONF_TAKE1, 128 ngx_conf_set_sec_slot, 129 NGX_MAIL_SRV_CONF_OFFSET, 130 offsetof(ngx_mail_ssl_conf_t, ticket_timeout), 131 NULL }, 132 126 133 ngx_null_command 127 134 }; 128 135 … … ngx_mail_ssl_create_conf(ngx_conf_t *cf) 184 191 scf->prefer_server_ciphers = NGX_CONF_UNSET; 185 192 scf->builtin_session_cache = NGX_CONF_UNSET; 186 193 scf->session_timeout = NGX_CONF_UNSET; 194 scf->ticket_timeout = NGX_CONF_UNSET; 187 195 188 196 return scf; 189 197 } … … ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) 205 213 ngx_conf_merge_value(conf->session_timeout, 206 214 prev->session_timeout, 300); 207 215 216 ngx_conf_merge_value(conf->ticket_timeout, 217 prev->ticket_timeout, 60*60*24*7); /* 1 week */ 218 208 219 ngx_conf_merge_value(conf->prefer_server_ciphers, 209 220 prev->prefer_server_ciphers, 0); 210 221 … … ngx_mail_ssl_merge_conf(ngx_conf_t *cf, void *parent, void *child) 317 328 318 329 if (ngx_ssl_session_cache(&conf->ssl, &ngx_mail_ssl_sess_id_ctx, 319 330 conf->builtin_session_cache, 320 conf->shm_zone, conf->session_timeout) 331 conf->shm_zone, conf->session_timeout, 332 &conf->ticket_timeout) 321 333 != NGX_OK) 322 334 { 323 335 return NGX_CONF_ERROR; … … ngx_mail_ssl_session_cache(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) 468 480 return NGX_CONF_ERROR; 469 481 } 470 482 471 scf->shm_zone->init = ngx_ssl_ session_cache_init;483 scf->shm_zone->init = ngx_ssl_cache_init; 472 484 473 485 continue; 474 486 } -
src/mail/ngx_mail_ssl_module.h
diff --git a/src/mail/ngx_mail_ssl_module.h b/src/mail/ngx_mail_ssl_module.h index 7f59b38..45b8214 100644
a b typedef struct { 31 31 ssize_t builtin_session_cache; 32 32 33 33 time_t session_timeout; 34 long ticket_timeout; 34 35 35 36 ngx_str_t certificate; 36 37 ngx_str_t certificate_key;
