Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

[openssl.org #3591] [PATCH v2] Implement Maximum Fragment Length Negotiation (RFC 4366).

234 views
Skip to first unread message

Tomasz Moń via RT

unread,
Nov 4, 2014, 4:26:55 PM11/4/14
to
Server automatically recognizes Maximum Fragment Length extension
included in Client Hello.

To enable clients use this extension following API are added:
* SSL_set_tlsext_max_fragment_length
* SSL_get_tlsext_max_fragment_length
* SSL_CTX_set_tlsext_max_fragment_length
---
apps/s_client.c | 31 +++++++++
doc/ssl/SSL_CTX_set_tlsext_max_fragment_length.pod | 78 ++++++++++++++++++++++
ssl/s3_lib.c | 30 +++++++++
ssl/s3_pkt.c | 30 ++++++++-
ssl/ssl.h | 20 ++++++
ssl/ssl_lib.c | 2 +
ssl/ssl_locl.h | 9 +++
ssl/ssl_sess.c | 1 +
ssl/t1_lib.c | 58 ++++++++++++++++
ssl/tls1.h | 17 +++++
10 files changed, 275 insertions(+), 1 deletion(-)
create mode 100644 doc/ssl/SSL_CTX_set_tlsext_max_fragment_length.pod

diff --git a/apps/s_client.c b/apps/s_client.c
index a6f972a..de4531c 100644
--- a/apps/s_client.c
+++ b/apps/s_client.c
@@ -210,6 +210,8 @@ static int c_showcerts=0;
static char *keymatexportlabel=NULL;
static int keymatexportlen=20;

+static char maxfraglen=0;
+
static void sc_usage(void);
static void print_stuff(BIO *berr,SSL *con,int full);
#ifndef OPENSSL_NO_TLSEXT
@@ -375,6 +377,7 @@ static void sc_usage(void)
BIO_printf(bio_err," -use_srtp profiles - Offer SRTP key management with a colon-separated profile list\n");
BIO_printf(bio_err," -keymatexport label - Export keying material using label\n");
BIO_printf(bio_err," -keymatexportlen len - Export len bytes of keying material (default 20)\n");
+ BIO_printf(bio_err," -maxfraglen len - Enable Maximum Fragment Length Negotiation (len values: 512, 1024, 2048 and 4096)\n");
}

#ifndef OPENSSL_NO_TLSEXT
@@ -1116,6 +1119,29 @@ static char *jpake_secret = NULL;
keymatexportlen=atoi(*(++argv));
if (keymatexportlen == 0) goto bad;
}
+ else if (strcmp(*argv,"-maxfraglen") == 0)
+ {
+ int len;
+ if (--argc < 1) goto bad;
+ len=atoi(*(++argv));
+ switch (len)
+ {
+ case 512:
+ maxfraglen=TLSEXT_max_fragment_length_2_TO_9;
+ break;
+ case 1024:
+ maxfraglen=TLSEXT_max_fragment_length_2_TO_10;
+ break;
+ case 2048:
+ maxfraglen=TLSEXT_max_fragment_length_2_TO_11;
+ break;
+ case 4096:
+ maxfraglen=TLSEXT_max_fragment_length_2_TO_12;
+ break;
+ default:
+ goto bad;
+ }
+ }
else
{
BIO_printf(bio_err,"unknown option %s\n",*argv);
@@ -1421,6 +1447,11 @@ bad:
#endif
#endif

+ if (maxfraglen)
+ {
+ SSL_CTX_set_tlsext_max_fragment_length(ctx, maxfraglen);
+ }
+
con=SSL_new(ctx);
if (sess_in)
{
diff --git a/doc/ssl/SSL_CTX_set_tlsext_max_fragment_length.pod b/doc/ssl/SSL_CTX_set_tlsext_max_fragment_length.pod
new file mode 100644
index 0000000..0b16467
--- /dev/null
+++ b/doc/ssl/SSL_CTX_set_tlsext_max_fragment_length.pod
@@ -0,0 +1,78 @@
+=pod
+
+=head1 NAME
+
+SSL_CTX_set_tlsext_max_fragment_length, SSL_set_tlsext_max_fragment_length, SSL_get_tlsext_max_fragment_length - enable Maximum Fragment Length Negotiation extension
+
+=head1 SYNOPSIS
+
+ #include <openssl/ssl.h>
+
+ long SSL_CTX_set_tlsext_max_fragment_length(SSL_CTX *ctx, long mode);
+ long SSL_set_tlsext_max_fragment_length(SSL *ssl, long mode);
+
+ long SSL_get_tlsext_max_fragment_length(SSL *ssl);
+
+=head1 DESCRIPTION
+
+SSL_CTX_set_tlsext_max_fragment_length() sets default maximum fragment
+length negotiation mode via value B<mode> to B<ctx>.
+This setting affects only SSL instances created after this function
+is called.
+
+SSL_set_tlsext_max_fragment_length() sets the maximum fragment length
+negotiation mode mode via value B<mode> to B<ssl>.
+This setting affects only SSL sessions created after this function
+is called.
+
+SSL_get_tlsext_max_fragment_length() gets the maximum fragment length
+negotiated in session B<ssl>.
+
+=head1 NOTES
+
+This extension is optional on server side. If server does not support this
+extension SSL_get_tlsext_max_fragment_length() will return
+TLSEXT_max_fragment_length_DISABLED.
+
+The following modes are available:
+
+=over 4
+
+=item TLSEXT_max_fragment_length_DISABLED
+
+Disables Maximum Fragment Length Negotiation (default).
+
+=item TLSEXT_max_fragment_length_2_TO_9
+
+Sets Maximum Fragment Length to 512.
+
+=item TLSEXT_max_fragment_length_2_TO_10
+
+Sets Maximum Fragment Length to 1024.
+
+=item TLSEXT_max_fragment_length_2_TO_11
+
+Sets Maximum Fragment Length to 2048.
+
+=item TLSEXT_max_fragment_length_2_TO_12
+
+Sets Maximum Fragment Length to 4096.
+
+=back
+
+=head1 RETURN VALUES
+
+SSL_CTX_set_tlsext_max_fragment_length() and SSL_set_tlsext_max_fragment_length() return 0.
+
+SSL_get_tlsext_max_fragment_length() returns Maximum Fragment Length
+negotiated in given connection B<ssl>.
+
+=head1 SEE ALSO
+
+L<SSL_set_tlsext_max_fragment_length(3)|SSL_set_tlsext_max_fragment_length(3)>, L<SSL_CTX_set_tlsext_max_fragment_length(3)|SSL_CTX_set_tlsext_max_fragment_length(3)>, L<SSL_get_tlsext_max_fragment_length(3)|SSL_get_tlsext_max_fragment_length(3)>
+
+=head1 HISTORY
+
+SSL_CTX_set_tlsext_max_fragment_length(), SSL_set_tlsext_max_fragment_length() and SSL_get_tlsext_max_fragment_length() have been added in OpenSSL 1.1.0.
+
+=cut
diff --git a/ssl/s3_lib.c b/ssl/s3_lib.c
index d670ff0..1b99585 100644
--- a/ssl/s3_lib.c
+++ b/ssl/s3_lib.c
@@ -3610,6 +3610,26 @@ long ssl3_ctrl(SSL *s, int cmd, long larg, void *parg)
break;
#endif /* !OPENSSL_NO_ECDH */
#ifndef OPENSSL_NO_TLSEXT
+ case SSL_CTRL_SET_TLSEXT_MAX_FRAGMENT_LENGTH:
+ if (((char)larg != TLSEXT_max_fragment_length_DISABLED) &&
+ (((char)larg < TLSEXT_max_fragment_length_2_TO_9) ||
+ ((char)larg > TLSEXT_max_fragment_length_2_TO_12)))
+ {
+ SSLerr(SSL_F_SSL3_CTRL, SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
+ return 0;
+ }
+ s->tlsext_max_fragment_length=(char)larg;
+ break;
+ case SSL_CTRL_GET_TLSEXT_MAX_FRAGMENT_LENGTH:
+ if (s->session == NULL)
+ {
+ ret = TLSEXT_max_fragment_length_DISABLED;
+ }
+ else
+ {
+ ret = s->session->tlsext_max_fragment_length;
+ }
+ break;
case SSL_CTRL_SET_TLSEXT_HOSTNAME:
if (larg == TLSEXT_NAMETYPE_host_name)
{
@@ -4156,6 +4176,16 @@ long ssl3_ctx_ctrl(SSL_CTX *ctx, int cmd, long larg, void *parg)
break;
#endif /* !OPENSSL_NO_ECDH */
#ifndef OPENSSL_NO_TLSEXT
+ case SSL_CTRL_SET_TLSEXT_MAX_FRAGMENT_LENGTH:
+ if (((char)larg != TLSEXT_max_fragment_length_DISABLED) &&
+ (((char)larg < TLSEXT_max_fragment_length_2_TO_9) ||
+ ((char)larg > TLSEXT_max_fragment_length_2_TO_12)))
+ {
+ SSLerr(SSL_F_SSL3_CTX_CTRL, SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH);
+ return 0;
+ }
+ ctx->tlsext_max_fragment_length=(char)larg;
+ break;
case SSL_CTRL_SET_TLSEXT_SERVERNAME_ARG:
ctx->tlsext_servername_arg=parg;
break;
diff --git a/ssl/s3_pkt.c b/ssl/s3_pkt.c
index ea45b86..fe163eb 100644
--- a/ssl/s3_pkt.c
+++ b/ssl/s3_pkt.c
@@ -555,6 +555,18 @@ printf("\n");
goto f_err;
}

+#ifndef OPENSSL_NO_TLSEXT
+ if (SSL_USE_MAX_FRAGMENT_LENGTH_EXT(s))
+ {
+ if (rr->length > SSL_GET_MAX_FRAGMENT_LENGTH(s)+extra)
+ {
+ al=SSL_AD_RECORD_OVERFLOW;
+ SSLerr(SSL_F_SSL3_GET_RECORD,SSL_R_PACKET_LENGTH_TOO_LONG);
+ goto f_err;
+ }
+ }
+#endif
+
rr->off=0;
/* So at this point the following is true
* ssl->s3->rrec.type is the type of record
@@ -697,6 +709,14 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len)
}

#if !defined(OPENSSL_NO_MULTIBLOCK) && EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK
+#ifndef OPENSSL_NO_TLSEXT
+ max_send_fragment = s->max_send_fragment;
+ if (SSL_USE_MAX_FRAGMENT_LENGTH_EXT(s))
+ {
+ if (max_send_fragment > SSL_GET_MAX_FRAGMENT_LENGTH(s))
+ max_send_fragment = SSL_GET_MAX_FRAGMENT_LENGTH(s);
+ }
+#endif
/*
* Depending on platform multi-block can deliver several *times*
* better performance. Downside is that it has to allocate
@@ -704,7 +724,7 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len)
* compromise is considered worthy.
*/
if (type==SSL3_RT_APPLICATION_DATA &&
- u_len >= 4*(max_send_fragment=s->max_send_fragment) &&
+ u_len >= 4*(max_send_fragment) &&
s->compress==NULL && s->msg_callback==NULL &&
!SSL_USE_ETM(s) && SSL_USE_EXPLICIT_IV(s) &&
EVP_CIPHER_flags(s->enc_write_ctx->cipher)&EVP_CIPH_FLAG_TLS1_1_MULTIBLOCK)
@@ -849,6 +869,14 @@ int ssl3_write_bytes(SSL *s, int type, const void *buf_, int len)
else
nw=n;

+#ifndef OPENSSL_NO_TLSEXT
+ if (SSL_USE_MAX_FRAGMENT_LENGTH_EXT(s))
+ {
+ if (nw > SSL_GET_MAX_FRAGMENT_LENGTH(s))
+ nw = SSL_GET_MAX_FRAGMENT_LENGTH(s);
+ }
+#endif
+
i=do_ssl3_write(s, type, &(buf[tot]), nw, 0);
if (i <= 0)
{
diff --git a/ssl/ssl.h b/ssl/ssl.h
index 343247c..4bf6310 100644
--- a/ssl/ssl.h
+++ b/ssl/ssl.h
@@ -557,6 +557,11 @@ struct ssl_session_st
struct ssl_session_st *prev,*next;
#ifndef OPENSSL_NO_TLSEXT
char *tlsext_hostname;
+ /* Maximum Fragment Length as per RFC 4366.
+ * If this value does not contain RFC 4366 allowed values (1-4)
+ * then either the Maximum Fragment Length Negotiation failed
+ * or was not performed at all. */
+ char tlsext_max_fragment_length;
#ifndef OPENSSL_NO_EC
size_t tlsext_ecpointformatlist_length;
unsigned char *tlsext_ecpointformatlist; /* peer's list */
@@ -1040,6 +1045,8 @@ struct ssl_ctx_st
/* TLS extensions servername callback */
int (*tlsext_servername_callback)(SSL*, int *, void *);
void *tlsext_servername_arg;
+ /* RFC 4366 Maximum Fragment Length Negotiation */
+ char tlsext_max_fragment_length;
/* RFC 4507 session ticket keys */
unsigned char tlsext_tick_key_name[16];
unsigned char tlsext_tick_hmac_key[16];
@@ -1485,6 +1492,16 @@ struct ssl_st
unsigned char *tlsext_ocsp_resp;
int tlsext_ocsp_resplen;

+ /* Maximum Fragment Length as per RFC 4366.
+ If this member contains one of the allowed values (1-4)
+ then we should include Maximum Fragment Length Negotiation
+ extension in Client Hello.
+ Please note that value of this member does not have direct
+ effect. The actual (binding) value is stored in SSL_SESSION,
+ as this extension is optional on server side.
+ */
+ char tlsext_max_fragment_length;
+
/* RFC4507 session ticket expected to be received or sent */
int tlsext_ticket_expected;
#ifndef OPENSSL_NO_EC
@@ -1800,6 +1817,8 @@ DECLARE_PEM_rw(SSL_SESSION, SSL_SESSION)
#define SSL_CTRL_GET_TLS_EXT_HEARTBEAT_PENDING 86
#define SSL_CTRL_SET_TLS_EXT_HEARTBEAT_NO_REQUESTS 87
#endif
+#define SSL_CTRL_SET_TLSEXT_MAX_FRAGMENT_LENGTH 120
+#define SSL_CTRL_GET_TLSEXT_MAX_FRAGMENT_LENGTH 121
#endif /* OPENSSL_NO_TLSEXT */

#define DTLS_CTRL_GET_TIMEOUT 73
@@ -3015,6 +3034,7 @@ void ERR_load_SSL_strings(void);
#define SSL_R_SSL3_EXT_INVALID_ECPOINTFORMAT 321
#define SSL_R_SSL3_EXT_INVALID_SERVERNAME 319
#define SSL_R_SSL3_EXT_INVALID_SERVERNAME_TYPE 320
+#define SSL_R_SSL3_EXT_INVALID_MAX_FRAGMENT_LENGTH 393
#define SSL_R_SSL3_SESSION_ID_TOO_LONG 300
#define SSL_R_SSL3_SESSION_ID_TOO_SHORT 222
#define SSL_R_SSLV3_ALERT_BAD_CERTIFICATE 1042
diff --git a/ssl/ssl_lib.c b/ssl/ssl_lib.c
index 43204de..e40d32e 100644
--- a/ssl/ssl_lib.c
+++ b/ssl/ssl_lib.c
@@ -346,6 +346,7 @@ SSL *SSL_new(SSL_CTX *ctx)
CRYPTO_add(&ctx->references,1,CRYPTO_LOCK_SSL_CTX);
s->ctx=ctx;
#ifndef OPENSSL_NO_TLSEXT
+ s->tlsext_max_fragment_length = ctx->tlsext_max_fragment_length;
s->tlsext_debug_cb = 0;
s->tlsext_debug_arg = NULL;
s->tlsext_ticket_expected = 0;
@@ -2030,6 +2031,7 @@ SSL_CTX *SSL_CTX_new(const SSL_METHOD *meth)
ret->max_send_fragment = SSL3_RT_MAX_PLAIN_LENGTH;

#ifndef OPENSSL_NO_TLSEXT
+ ret->tlsext_max_fragment_length = 0;
ret->tlsext_servername_callback = 0;
ret->tlsext_servername_arg = NULL;
/* Setup RFC4507 ticket keys */
diff --git a/ssl/ssl_locl.h b/ssl/ssl_locl.h
index 1fd6bb1..770dc97 100644
--- a/ssl/ssl_locl.h
+++ b/ssl/ssl_locl.h
@@ -463,6 +463,15 @@
((SSL_IS_DTLS(s) && s->client_version <= DTLS1_2_VERSION) || \
(!SSL_IS_DTLS(s) && s->client_version >= TLS1_2_VERSION))

+#ifndef OPENSSL_NO_TLSEXT
+#define SSL_USE_MAX_FRAGMENT_LENGTH_EXT(s) \
+ (s->session) && \
+ ((s->session->tlsext_max_fragment_length >= TLSEXT_max_fragment_length_2_TO_9) && \
+ (s->session->tlsext_max_fragment_length <= TLSEXT_max_fragment_length_2_TO_12))
+#define SSL_GET_MAX_FRAGMENT_LENGTH(s) \
+ (2 << (7 + s->session->tlsext_max_fragment_length))
+#endif
+
#ifdef TLSEXT_TYPE_encrypt_then_mac
#define SSL_USE_ETM(s) (s->s3->flags & TLS1_FLAGS_ENCRYPT_THEN_MAC)
#else
diff --git a/ssl/ssl_sess.c b/ssl/ssl_sess.c
index 3f9bad1..b905d49 100644
--- a/ssl/ssl_sess.c
+++ b/ssl/ssl_sess.c
@@ -206,6 +206,7 @@ SSL_SESSION *SSL_SESSION_new(void)
ss->compress_meth=0;
#ifndef OPENSSL_NO_TLSEXT
ss->tlsext_hostname = NULL;
+ ss->tlsext_max_fragment_length = 0;
#ifndef OPENSSL_NO_EC
ss->tlsext_ecpointformatlist_length = 0;
ss->tlsext_ecpointformatlist = NULL;
diff --git a/ssl/t1_lib.c b/ssl/t1_lib.c
index d0e0b0f..70f7e1a 100644
--- a/ssl/t1_lib.c
+++ b/ssl/t1_lib.c
@@ -1184,6 +1184,17 @@ unsigned char *ssl_add_clienthello_tlsext(SSL *s, unsigned char *buf, unsigned c
ret+=size_str;
}

+ /* Add Max Fragment Length extension if user enabled it. */
+ if ((s->tlsext_max_fragment_length >= TLSEXT_max_fragment_length_2_TO_9) &&
+ (s->tlsext_max_fragment_length <= TLSEXT_max_fragment_length_2_TO_12))
+ {
+ if ((limit - ret - 5) < 0) return NULL;
+
+ s2n(TLSEXT_TYPE_max_fragment_length,ret);
+ s2n(1,ret);
+ *(ret++) = (unsigned char) s->tlsext_max_fragment_length;
+ }
+
/* Add RI if renegotiating */
if (s->renegotiate)
{
@@ -1558,6 +1569,16 @@ unsigned char *ssl_add_serverhello_tlsext(SSL *s, unsigned char *buf, unsigned c
s2n(0,ret);
}

+ /* If client sent Max Fragment Length extension accept it by replying back. */
+ if (SSL_USE_MAX_FRAGMENT_LENGTH_EXT(s))
+ {
+ if ((limit - ret - 5) < 0) return NULL;
+
+ s2n(TLSEXT_TYPE_max_fragment_length,ret);
+ s2n(1,ret);
+ *(ret++) = (unsigned char) s->session->tlsext_max_fragment_length;
+ }
+
if(s->s3->send_connection_binding)
{
int el;
@@ -2080,6 +2101,21 @@ static int ssl_scan_clienthello_tlsext(SSL *s, unsigned char **p, unsigned char
}

}
+ else if (type == TLSEXT_TYPE_max_fragment_length)
+ {
+ if (size != 1 ||
+ (data[0] < TLSEXT_max_fragment_length_2_TO_9) ||
+ (data[0] > TLSEXT_max_fragment_length_2_TO_12))
+ {
+ *al = SSL_AD_ILLEGAL_PARAMETER;
+ return 0;
+ }
+
+ /* data[0] contains valid max fragment length.
+ * Store it in session, so it'll become binding for us
+ * and we'll include it in Server Hello. */
+ s->session->tlsext_max_fragment_length = data[0];
+ }
#ifndef OPENSSL_NO_SRP
else if (type == TLSEXT_TYPE_srp)
{
@@ -2555,6 +2591,28 @@ static int ssl_scan_serverhello_tlsext(SSL *s, unsigned char **p, unsigned char
tlsext_servername = 1;
}

+ else if (type == TLSEXT_TYPE_max_fragment_length)
+ {
+ if (size != 1 ||
+ (data[0] < TLSEXT_max_fragment_length_2_TO_9) ||
+ (data[0] > TLSEXT_max_fragment_length_2_TO_12))
+ {
+ *al = SSL_AD_ILLEGAL_PARAMETER;
+ return 0;
+ }
+
+ if (data[0] == s->tlsext_max_fragment_length)
+ {
+ /* Maximum Fragment Length Negotiation succeeded.
+ * The Negotiated Maximum Fragment Length is binding now. */
+ s->session->tlsext_max_fragment_length = data[0];
+ }
+ else
+ {
+ *al = SSL_AD_ILLEGAL_PARAMETER;
+ return 0;
+ }
+ }
#ifndef OPENSSL_NO_EC
else if (type == TLSEXT_TYPE_ec_point_formats)
{
diff --git a/ssl/tls1.h b/ssl/tls1.h
index e8188ec..b371596 100644
--- a/ssl/tls1.h
+++ b/ssl/tls1.h
@@ -309,6 +309,14 @@ extern "C" {
#define TLSEXT_curve_P_256 23
#define TLSEXT_curve_P_384 24

+/* OpenSSL value to disable maximum fragment length extension */
+#define TLSEXT_max_fragment_length_DISABLED 0
+/* Allowed values for max fragment length extension */
+#define TLSEXT_max_fragment_length_2_TO_9 1
+#define TLSEXT_max_fragment_length_2_TO_10 2
+#define TLSEXT_max_fragment_length_2_TO_11 3
+#define TLSEXT_max_fragment_length_2_TO_12 4
+
#ifndef OPENSSL_NO_TLSEXT

#define TLSEXT_MAXLEN_host_name 255
@@ -339,6 +347,12 @@ int SSL_check_chain(SSL *s, X509 *x, EVP_PKEY *pk, STACK_OF(X509) *chain);
#define SSL_set_tlsext_host_name(s,name) \
SSL_ctrl(s,SSL_CTRL_SET_TLSEXT_HOSTNAME,TLSEXT_NAMETYPE_host_name,(char *)name)

+#define SSL_set_tlsext_max_fragment_length(s, type) \
+SSL_ctrl(s,SSL_CTRL_SET_TLSEXT_MAX_FRAGMENT_LENGTH,type,NULL)
+
+#define SSL_get_tlsext_max_fragment_length(s) \
+SSL_ctrl(s,SSL_CTRL_GET_TLSEXT_MAX_FRAGMENT_LENGTH,0,NULL)
+
#define SSL_set_tlsext_debug_callback(ssl, cb) \
SSL_callback_ctrl(ssl,SSL_CTRL_SET_TLSEXT_DEBUG_CB,(void (*)(void))cb)

@@ -366,6 +380,9 @@ SSL_ctrl(ssl,SSL_CTRL_GET_TLSEXT_STATUS_REQ_OCSP_RESP,0, (void *)arg)
#define SSL_set_tlsext_status_ocsp_resp(ssl, arg, arglen) \
SSL_ctrl(ssl,SSL_CTRL_SET_TLSEXT_STATUS_REQ_OCSP_RESP,arglen, (void *)arg)

+#define SSL_CTX_set_tlsext_max_fragment_length(ctx, type) \
+SSL_CTX_ctrl(ctx,SSL_CTRL_SET_TLSEXT_MAX_FRAGMENT_LENGTH,type,NULL)
+
#define SSL_CTX_set_tlsext_servername_callback(ctx, cb) \
SSL_CTX_callback_ctrl(ctx,SSL_CTRL_SET_TLSEXT_SERVERNAME_CB,(void (*)(void))cb)

--
2.1.1

______________________________________________________________________
OpenSSL Project http://www.openssl.org
Development Mailing List opens...@openssl.org
Automated List Manager majo...@openssl.org

0 new messages