gnutls-commit
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU gnutls branch, master, updated. gnutls_2_11_6-299-g5d1476c


From: Nikos Mavrogiannopoulos
Subject: [SCM] GNU gnutls branch, master, updated. gnutls_2_11_6-299-g5d1476c
Date: Sun, 13 Mar 2011 17:13:20 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU gnutls".

http://git.savannah.gnu.org/cgit/gnutls.git/commit/?id=5d1476cc273409164d0c850b907f28a74e26f563

The branch, master has been updated
       via  5d1476cc273409164d0c850b907f28a74e26f563 (commit)
       via  541aed3982a0b4e6d968ff2d1a38cfd4306f2d2b (commit)
       via  df7d8850afcd11ffa0801ace3f3c742f92327317 (commit)
       via  222df46ca4ea561df6b944cfbb830f7c3b2b3ab1 (commit)
      from  8490141c416eda633965850b9439c88d204ec3f3 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 5d1476cc273409164d0c850b907f28a74e26f563
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sun Mar 13 18:13:15 2011 +0100

    Use DTLS 1.0 instead of SSL 3.0 headers on client hello in DTLS.

commit 541aed3982a0b4e6d968ff2d1a38cfd4306f2d2b
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sun Mar 13 18:11:39 2011 +0100

    Added photuris-like resource protection on the server. Added 
gnutls_dtls_cookie_send(), gnutls_dtls_cookie_verify() and 
gnutls_dtls_cookie_set() to avoid initializing a session before cookie is 
verified.

commit df7d8850afcd11ffa0801ace3f3c742f92327317
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sun Mar 13 18:07:52 2011 +0100

    added gnutls_key_generate() to API.

commit 222df46ca4ea561df6b944cfbb830f7c3b2b3ab1
Author: Nikos Mavrogiannopoulos <address@hidden>
Date:   Sun Mar 13 13:59:16 2011 +0100

    Avoid the usage of structures where the attribute packed is assumed.

-----------------------------------------------------------------------

Summary of changes:
 lib/crypto-api.c                |   38 ++++++
 lib/ext_session_ticket.c        |   48 +++------
 lib/gnutls_dtls.c               |  243 +++++++++++++++++++++++++++++++++++++++
 lib/gnutls_errors.c             |    1 +
 lib/gnutls_handshake.c          |    5 +-
 lib/includes/gnutls/dtls.h      |   18 +++
 lib/includes/gnutls/gnutls.h.in |    3 +
 lib/libgnutls.map               |    4 +
 src/udp-serv.c                  |   43 ++++++-
 9 files changed, 364 insertions(+), 39 deletions(-)

diff --git a/lib/crypto-api.c b/lib/crypto-api.c
index b5f6cc5..f7f200c 100644
--- a/lib/crypto-api.c
+++ b/lib/crypto-api.c
@@ -28,6 +28,7 @@
 #include <gnutls_cipher_int.h>
 #include <gnutls_datum.h>
 #include <gnutls/crypto.h>
+#include <random.h>
 #include <crypto.h>
 
 /**
@@ -457,3 +458,40 @@ gnutls_hash_fast (gnutls_digest_algorithm_t algorithm,
 {
   return _gnutls_hash_fast (algorithm, text, textlen, digest);
 }
+
+/**
+ * gnutls_key_generate:
+ * @key: is a pointer to a #gnutls_datum_t which will contain a newly
+ * created key.
+ * @key_size: The number of bytes of the key.
+ *
+ * Generates a random key of @key_bytes size.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, or an
+ * error code.
+ *
+ * Since: 3.0.0
+ **/
+int
+gnutls_key_generate (gnutls_datum_t * key, unsigned int key_size)
+{
+  int ret;
+
+  key->size = key_size;
+  key->data = gnutls_malloc (key->size);
+  if (!key->data)
+    {
+      gnutls_assert ();
+      return GNUTLS_E_MEMORY_ERROR;
+    }
+
+  ret = _gnutls_rnd (GNUTLS_RND_RANDOM, key->data, key->size);
+  if (ret < 0)
+    {
+      gnutls_assert ();
+      _gnutls_free_datum (key);
+      return ret;
+    }
+
+  return 0;
+}
diff --git a/lib/ext_session_ticket.c b/lib/ext_session_ticket.c
index 5f141c7..92a2c93 100644
--- a/lib/ext_session_ticket.c
+++ b/lib/ext_session_ticket.c
@@ -67,12 +67,10 @@ extension_entry_st ext_mod_session_ticket = {
   .deinit_func = session_ticket_deinit_data,
 };
 
-struct gnutls_session_ticket_key_st
-{
-  opaque key_name[SESSION_TICKET_KEY_NAME_SIZE];
-  opaque key[SESSION_TICKET_KEY_SIZE];
-  opaque mac_secret[SESSION_TICKET_MAC_SECRET_SIZE];
-};
+#define SESSION_KEY_SIZE 
(SESSION_TICKET_KEY_NAME_SIZE+SESSION_TICKET_KEY_SIZE+SESSION_TICKET_MAC_SECRET_SIZE)
+#define NAME_POS (0)
+#define KEY_POS (SESSION_TICKET_KEY_NAME_SIZE)
+#define MAC_SECRET_POS (SESSION_TICKET_KEY_NAME_SIZE+SESSION_TICKET_KEY_SIZE)
 
 typedef struct
 {
@@ -83,7 +81,7 @@ typedef struct
   opaque *session_ticket;
   int session_ticket_len;
 
-  struct gnutls_session_ticket_key_st key;
+  opaque key[SESSION_KEY_SIZE];
 } session_ticket_ext_st;
 
 struct ticket
@@ -132,7 +130,7 @@ decrypt_ticket (gnutls_session_t session, 
session_ticket_ext_st * priv,
   int ret;
 
   /* Check the integrity of ticket using HMAC-SHA-256. */
-  mac_secret.data = (void *) priv->key.mac_secret;
+  mac_secret.data = (void *) &priv->key[MAC_SECRET_POS];
   mac_secret.size = MAC_SECRET_SIZE;
   ret = digest_ticket (&mac_secret, ticket, final);
   if (ret < 0)
@@ -148,7 +146,7 @@ decrypt_ticket (gnutls_session_t session, 
session_ticket_ext_st * priv,
     }
 
   /* Decrypt encrypted_state using 128-bit AES in CBC mode. */
-  key.data = (void *) priv->key.key;
+  key.data = (void *) &priv->key[KEY_POS];
   key.size = KEY_SIZE;
   IV.data = ticket->IV;
   IV.size = IV_SIZE;
@@ -223,7 +221,7 @@ encrypt_ticket (gnutls_session_t session, 
session_ticket_ext_st * priv,
   _gnutls_free_datum (&state);
 
   /* Encrypt state using 128-bit AES in CBC mode. */
-  key.data = (void *) priv->key.key;
+  key.data = (void *) &priv->key[KEY_POS];
   key.size = KEY_SIZE;
   IV.data = priv->session_ticket_IV;
   IV.size = IV_SIZE;
@@ -247,12 +245,12 @@ encrypt_ticket (gnutls_session_t session, 
session_ticket_ext_st * priv,
     }
 
   /* Fill the ticket structure to compute MAC. */
-  memcpy (ticket->key_name, priv->key.key_name, KEY_NAME_SIZE);
+  memcpy (ticket->key_name, &priv->key[NAME_POS], KEY_NAME_SIZE);
   memcpy (ticket->IV, IV.data, IV.size);
   ticket->encrypted_state_len = encrypted_state.size;
   ticket->encrypted_state = encrypted_state.data;
 
-  mac_secret.data = priv->key.mac_secret;
+  mac_secret.data = &priv->key[MAC_SECRET_POS];
   mac_secret.size = MAC_SECRET_SIZE;
   ret = digest_ticket (&mac_secret, ticket, ticket->mac);
   if (ret < 0)
@@ -305,7 +303,7 @@ session_ticket_recv_params (gnutls_session_t session,
 
       /* If the key name of the ticket does not match the one that we
          hold, issue a new ticket. */
-      if (memcmp (ticket.key_name, priv->key.key_name, KEY_NAME_SIZE))
+      if (memcmp (ticket.key_name, &priv->key[NAME_POS], KEY_NAME_SIZE))
         {
           priv->session_ticket_renew = 1;
           return 0;
@@ -482,25 +480,7 @@ error:
 int
 gnutls_session_ticket_key_generate (gnutls_datum_t * key)
 {
-  int ret;
-
-  key->size = sizeof (struct gnutls_session_ticket_key_st);
-  key->data = gnutls_malloc (key->size);
-  if (!key->data)
-    {
-      gnutls_assert ();
-      return GNUTLS_E_MEMORY_ERROR;
-    }
-
-  ret = _gnutls_rnd (GNUTLS_RND_RANDOM, key->data, key->size);
-  if (ret < 0)
-    {
-      gnutls_assert ();
-      _gnutls_free_datum (key);
-      return ret;
-    }
-
-  return 0;
+  return gnutls_key_generate(key, SESSION_KEY_SIZE);
 }
 
 /**
@@ -565,7 +545,7 @@ gnutls_session_ticket_enable_server (gnutls_session_t 
session,
   extension_priv_data_t epriv;
 
   if (!session || !key
-      || key->size != sizeof (struct gnutls_session_ticket_key_st))
+      || key->size != SESSION_KEY_SIZE)
     {
       gnutls_assert ();
       return GNUTLS_E_INVALID_REQUEST;
@@ -579,7 +559,7 @@ gnutls_session_ticket_enable_server (gnutls_session_t 
session,
     }
   epriv.ptr = priv;
 
-  ret = _gnutls_rnd (GNUTLS_RND_RANDOM, priv->session_ticket_IV, IV_SIZE);
+  ret = _gnutls_rnd (GNUTLS_RND_NONCE, priv->session_ticket_IV, IV_SIZE);
   if (ret < 0)
     {
       gnutls_assert ();
diff --git a/lib/gnutls_dtls.c b/lib/gnutls_dtls.c
index 36262c9..708e262 100644
--- a/lib/gnutls_dtls.c
+++ b/lib/gnutls_dtls.c
@@ -366,6 +366,8 @@ void gnutls_dtls_set_mtu (gnutls_session_t session, 
unsigned int mtu)
  * application data. I.e. DTLS headers are subtracted from the
  * actual MTU.
  *
+ * Returns: the maximum allowed transfer unit.
+ *
  **/
 unsigned int gnutls_dtls_get_mtu (gnutls_session_t session)
 {
@@ -377,3 +379,244 @@ int ret;
   else
     return session->internals.dtls.mtu - RECORD_HEADER_SIZE(session);
 }
+
+#define COOKIE_SIZE 19
+#define COOKIE_MAC_SIZE 16
+
+/* record seq || hsk read seq || hsk write seq ||   MAC
+ *   1 byte         1 byte           1 byte       16 bytes
+ *
+ * total 19 bytes
+ */
+
+#define C_HASH GNUTLS_MAC_SHA1
+#define C_HASH_SIZE 20
+
+/**
+ * gnutls_dtls_cookie_send:
+ * @key: is a random key to be used at cookie generation
+ * @client_data: contains data identifying the client (i.e. address)
+ * @client_data_size: The size of client's data
+ * @cookie: The previous cookie returned by gnutls_dtls_cookie_verify()
+ * @ptr: A transport pointer to be used by @push_func
+ * @push_func: A function that will be used to reply
+ *
+ * This function can be used to prevent denial of service
+ * attacks to a DTLS server by requiring the client to
+ * reply using a cookie sent by this function. That way
+ * it can be ensured that a client we allocated resources
+ * for (i.e. #gnutls_session_t) is the one that the 
+ * original incoming packet was originated from.
+ *
+ * Returns: the number of bytes sent, or a negative error code.  
+ *
+ **/
+int gnutls_dtls_cookie_send(gnutls_datum_t* key, void* client_data, size_t 
client_data_size, 
+  gnutls_cookie_st* cookie,
+  gnutls_transport_ptr_t ptr, gnutls_push_func push_func)
+{
+
+opaque hvr[20+DTLS_HANDSHAKE_HEADER_SIZE+COOKIE_SIZE];
+int hvr_size = 0, ret;
+uint8_t digest[C_HASH_SIZE];
+
+  if (key == NULL || key->data == NULL || key->size == 0)
+    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+/* send
+ *  struct {
+ *    ContentType type - 1 byte GNUTLS_HANDSHAKE;
+ *    ProtocolVersion version; - 2 bytes (254,255)
+ *    uint16 epoch; - 2 bytes (0, 0)
+ *    uint48 sequence_number; - 4 bytes (0,0,0,0)
+ *    uint16 length; - 2 bytes (COOKIE_SIZE+1+2)+DTLS_HANDSHAKE_HEADER_SIZE
+ *    opaque fragment[DTLSPlaintext.length];
+ *  } DTLSPlaintext;
+ *
+ *
+ * struct {
+ *    HandshakeType msg_type; 1 byte - GNUTLS_HANDSHAKE_HELLO_VERIFY_REQUEST
+ *    uint24 length; - COOKIE_SIZE+3
+ *    uint16 message_seq; - 2 bytes (0,0)
+ *    uint24 fragment_offset; - 3 bytes (0,0,0)
+ *    uint24 fragment_length; - same as length
+ * }
+ *
+ * struct {
+ *   ProtocolVersion server_version;
+ *   opaque cookie<0..32>;
+ * } HelloVerifyRequest;
+ */ 
+
+  hvr[hvr_size++] = GNUTLS_HANDSHAKE;
+  /* version */
+  hvr[hvr_size++] = 254;
+  hvr[hvr_size++] = 255;
+  
+  /* epoch + seq */
+  memset(&hvr[hvr_size], 0, 8);
+  hvr_size += 8;
+
+  /* length */
+  _gnutls_write_uint16(DTLS_HANDSHAKE_HEADER_SIZE+COOKIE_SIZE+3, 
&hvr[hvr_size]);
+  hvr_size += 2;
+
+  /* now handshake headers */
+  hvr[hvr_size++] = GNUTLS_HANDSHAKE_HELLO_VERIFY_REQUEST;
+  _gnutls_write_uint24(COOKIE_SIZE+3, &hvr[hvr_size]);
+  hvr_size += 3;
+  
+  /* handshake seq */
+  memset(&hvr[hvr_size], 0, 2);
+  hvr_size += 2;
+
+  _gnutls_write_uint24(0, &hvr[hvr_size]);
+  hvr_size += 3;
+
+  _gnutls_write_uint24(COOKIE_SIZE+3, &hvr[hvr_size]);
+  hvr_size += 3;
+
+  /* version */
+  hvr[hvr_size++] = 254;
+  hvr[hvr_size++] = 255;
+  hvr[hvr_size++] = COOKIE_SIZE;
+
+  ret = _gnutls_hmac_fast(C_HASH, key->data, key->size, client_data, 
client_data_size, digest);
+  if (ret < 0)
+    return gnutls_assert_val(ret);
+
+  if (cookie && cookie->cookie_size > 3)
+    {
+      hvr[hvr_size++] = cookie->cookie[0]+1/* record */;
+      hvr[hvr_size++] = cookie->cookie[1]+1/* hsk read seq*/;
+      hvr[hvr_size++] = cookie->cookie[2]+1/* hsk write seq */;
+    }
+  else
+    {
+      hvr[hvr_size++] = 1;
+      hvr[hvr_size++] = 1;
+      hvr[hvr_size++] = 1;
+    }
+
+  memcpy(&hvr[hvr_size], digest, COOKIE_MAC_SIZE);
+  hvr_size+= COOKIE_MAC_SIZE;
+
+  ret = push_func(ptr, hvr, hvr_size);
+  if (ret < 0)
+    ret = GNUTLS_E_PUSH_ERROR;
+
+  return ret;
+}
+
+/**
+ * gnutls_dtls_cookie_verify:
+ * @key: is a random key to be used at cookie generation
+ * @client_data: contains data identifying the client (i.e. address)
+ * @client_data_size: The size of client's data
+ * @msg: An incoming message that initiates a connection.
+ * @msg_size: The size of the message.
+ * @cookie: The cookie of this client.
+ *
+ * This function will verify an incoming message for
+ * a valid cookie. If a valid cookie is returned then
+ * it should be associated with the session using
+ * gnutls_dtls_cookie_set();
+ *
+ * Returns: zero on success, or a negative error code.  
+ *
+ **/
+int gnutls_dtls_cookie_verify(gnutls_datum_t* key, 
+  void* client_data, size_t client_data_size, 
+  void* _msg, size_t msg_size, gnutls_cookie_st* out)
+{
+gnutls_datum_t cookie;
+int sid_size;
+int pos, ret;
+uint8_t * msg = _msg;
+uint8_t digest[C_HASH_SIZE];
+
+  if (key == NULL || key->data == NULL || key->size == 0)
+    return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+  /* format:
+   * version - 2 bytes
+   * random - 32 bytes
+   * session_id - 1 byte length + content
+   * cookie - 1 byte length + content
+   */
+
+  pos = 34+DTLS_RECORD_HEADER_SIZE+DTLS_HANDSHAKE_HEADER_SIZE;
+
+  if (msg_size < pos+1)
+    return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
+
+  sid_size = msg[pos++];
+
+  if (sid_size > 32 || msg_size < pos+sid_size+1)
+    return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
+
+  pos += sid_size;
+  cookie.size = msg[pos++];
+
+  if (msg_size < pos+cookie.size+1)
+    return gnutls_assert_val(GNUTLS_E_UNEXPECTED_PACKET_LENGTH);
+  
+  cookie.data = &msg[pos];
+  if (cookie.size != COOKIE_SIZE)
+    {
+      if (cookie.size > 0) _gnutls_audit_log("Received cookie with illegal 
size %d. Expected %d\n", (int)cookie.size, COOKIE_SIZE);
+      return gnutls_assert_val(GNUTLS_E_BAD_COOKIE);
+    }
+
+  ret = _gnutls_hmac_fast(C_HASH, key->data, key->size, client_data, 
client_data_size, digest);
+  if (ret < 0)
+    return gnutls_assert_val(ret);
+
+  if (memcmp(digest, &cookie.data[3], COOKIE_MAC_SIZE) != 0)
+    return gnutls_assert_val(GNUTLS_E_BAD_COOKIE);
+  
+  memcpy(out->cookie, cookie.data, cookie.size);
+  out->cookie_size = cookie.size;
+
+  return 0;
+}
+
+/**
+ * gnutls_dtls_cookie_set:
+ * @session: a new session
+ * @cookie: contains the client's cookie
+ *
+ * This function will associate the received cookie by
+ * the client, with the newly established session.
+ *
+ * Returns: zero on success, or a negative error code.  
+ *
+ **/
+void gnutls_dtls_cookie_set(gnutls_session_t session, gnutls_cookie_st* st)
+{
+  record_parameters_st *params;
+  int ret;
+
+  if (st == NULL || st->cookie_size == 0)
+    return;
+
+  /* we do not care about read_params, since we accept anything
+   * the peer sends.
+   */
+  ret = _gnutls_epoch_get (session, EPOCH_WRITE_CURRENT, &params);
+  if (ret < 0)
+    return;
+
+  if (st->cookie_size < 3)
+    return;
+
+  params->write.sequence_number.i[7] = st->cookie[0];
+
+  session->internals.dtls.hsk_read_seq = st->cookie[1];
+  session->internals.dtls.hsk_write_seq = st->cookie[2];
+
+fprintf(stderr, "record send seq: %d\n", (int)st->cookie[0]);
+fprintf(stderr, "hsk read seq: %d\n", (int)st->cookie[1]);
+fprintf(stderr, "hsk write seq: %d\n", (int)st->cookie[2]);
+
+}
diff --git a/lib/gnutls_errors.c b/lib/gnutls_errors.c
index 4d499ab..d9548e3 100644
--- a/lib/gnutls_errors.c
+++ b/lib/gnutls_errors.c
@@ -173,6 +173,7 @@ static const gnutls_error_entry error_algorithms[] = {
   ERROR_ENTRY (N_("The given memory buffer is too short to hold parameters."),
                GNUTLS_E_SHORT_MEMORY_BUFFER, 1),
   ERROR_ENTRY (N_("The request is invalid."), GNUTLS_E_INVALID_REQUEST, 1),
+  ERROR_ENTRY (N_("The cookie was bad."), GNUTLS_E_BAD_COOKIE, 1),
   ERROR_ENTRY (N_("An illegal parameter has been received."),
                GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER, 1),
   ERROR_ENTRY (N_("Error while reading file."), GNUTLS_E_FILE_ERROR, 1),
diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c
index 296d06a..7e0608d 100644
--- a/lib/gnutls_handshake.c
+++ b/lib/gnutls_handshake.c
@@ -1960,7 +1960,10 @@ _gnutls_send_client_hello (gnutls_session_t session, int 
again)
            * that do not support TLS 1.2 and don't know
            * how 3,3 version of record packets look like.
            */
-          _gnutls_record_set_default_version (session, 3, 0);
+          if (!IS_DTLS(session))
+            _gnutls_record_set_default_version (session, 3, 0);
+          else
+            _gnutls_record_set_default_version (session, 254, 255);
         }
 
       /* In order to know when this session was initiated.
diff --git a/lib/includes/gnutls/dtls.h b/lib/includes/gnutls/dtls.h
index 9177cf8..9f5dde9 100644
--- a/lib/includes/gnutls/dtls.h
+++ b/lib/includes/gnutls/dtls.h
@@ -36,12 +36,30 @@ extern "C"
 {
 #endif
 
+#define GNUTLS_COOKIE_KEY_SIZE 16
+
 void gnutls_dtls_set_timeouts (gnutls_session_t session, unsigned int 
retrans_timeout,
   unsigned int total_timeout);
 
 unsigned int gnutls_dtls_get_mtu (gnutls_session_t session);
 void gnutls_dtls_set_mtu (gnutls_session_t session, unsigned int mtu);
 
+typedef struct {
+  unsigned char cookie[255];
+  size_t cookie_size;
+} gnutls_cookie_st;
+
+int gnutls_dtls_cookie_send(gnutls_datum_t* key, void* client_data, size_t 
client_data_size, 
+  gnutls_cookie_st* cookie,
+  gnutls_transport_ptr_t ptr, gnutls_push_func push_func);
+
+
+int gnutls_dtls_cookie_verify(gnutls_datum_t* key, 
+  void* client_data, size_t client_data_size, 
+  void* _msg, size_t msg_size, gnutls_cookie_st* cookie);
+
+void gnutls_dtls_cookie_set(gnutls_session_t session, gnutls_cookie_st* st);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
index 7e70a33..5933f4d 100644
--- a/lib/includes/gnutls/gnutls.h.in
+++ b/lib/includes/gnutls/gnutls.h.in
@@ -847,6 +847,8 @@ extern "C"
   int gnutls_session_ticket_enable_server (gnutls_session_t session,
                                            const gnutls_datum_t * key);
 
+  int gnutls_key_generate (gnutls_datum_t * key, unsigned int key_size);
+
 /* if you just want some defaults, use the following.
  */
   int gnutls_priority_init (gnutls_priority_t * priority_cache,
@@ -1711,6 +1713,7 @@ extern "C"
 #define GNUTLS_E_CRYPTODEV_DEVICE_ERROR -212
 
 #define GNUTLS_E_CHANNEL_BINDING_NOT_AVAILABLE -213
+#define GNUTLS_E_BAD_COOKIE -214
 
 /* PKCS11 related */
 #define GNUTLS_E_PKCS11_ERROR -300
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
index b91d291..aa76fde 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -696,6 +696,10 @@ GNUTLS_3_0_0 {
        gnutls_dtls_get_mtu;
        gnutls_dtls_set_mtu;
         gnutls_record_recv_seq;
+       gnutls_key_generate;
+       gnutls_dtls_cookie_verify;
+       gnutls_dtls_cookie_send;
+       gnutls_dtls_cookie_set;
 } GNUTLS_2_12;
 
 GNUTLS_PRIVATE {
diff --git a/src/udp-serv.c b/src/udp-serv.c
index f77961c..9202565 100644
--- a/src/udp-serv.c
+++ b/src/udp-serv.c
@@ -29,11 +29,23 @@ int udp_server(const char* name, int port, int mtu)
     char buffer[MAX_BUFFER];
     priv_data_st priv;
     gnutls_session_t session;
+    gnutls_datum_t cookie_key;
+    gnutls_cookie_st cookie;
     unsigned char sequence[8];
 
+    ret = gnutls_key_generate(&cookie_key, GNUTLS_COOKIE_KEY_SIZE);
+    if (ret < 0)
+      {
+        fprintf(stderr, "Cannot generate key\n");
+        exit(1);
+      }
+
     ret = listen_socket (name, port, SOCK_DGRAM);
     if (ret < 0)
-      exit (1);
+      {
+        fprintf(stderr, "Cannot listen\n");
+        exit (1);
+      }
 
     for (;;)
       {
@@ -43,16 +55,39 @@ int udp_server(const char* name, int port, int mtu)
           continue;
 
         cli_addr_size = sizeof(cli_addr);
-        ret = recvfrom(sock, buffer, 1, MSG_PEEK, (struct sockaddr*)&cli_addr, 
&cli_addr_size);
-        if (ret == 1)
-          printf ("Accepted connection from %s\n",
+        ret = recvfrom(sock, buffer, sizeof(buffer), MSG_PEEK, (struct 
sockaddr*)&cli_addr, &cli_addr_size);
+        if (ret > 0)
+          {
+            memset(&cookie, 0, sizeof(cookie));
+            ret = gnutls_dtls_cookie_verify(&cookie_key, &cli_addr, 
sizeof(cli_addr), buffer, ret, &cookie);
+            if (ret < 0) /* cookie not valid */
+              {
+                priv_data_st s;
+                
+                memset(&s,0,sizeof(s));
+                s.fd = sock;
+                s.cli_addr = (void*)&cli_addr;
+                s.cli_addr_size = sizeof(cli_addr);
+                
+                printf("Sending hello verify request to %s\n", human_addr 
((struct sockaddr *)
+                  &cli_addr, sizeof(cli_addr), buffer, sizeof(buffer)));
+                gnutls_dtls_cookie_send(&cookie_key, &cli_addr, 
sizeof(cli_addr), &cookie, (gnutls_transport_ptr_t)&s, push_func);
+
+                /* discard peeked data*/
+                recvfrom(sock, buffer, sizeof(buffer), 0, (struct 
sockaddr*)&cli_addr, &cli_addr_size);
+                usleep(100);
+                continue;
+              }
+            printf ("Accepted connection from %s\n",
                             human_addr ((struct sockaddr *)
                                         &cli_addr, sizeof(cli_addr), buffer,
                                         sizeof (buffer)));
+          }
         else
           continue;
 
         session = initialize_session(1);
+        gnutls_dtls_cookie_set(session, &cookie);
         if (mtu) gnutls_dtls_set_mtu(session, mtu);
 
         priv.session = session;


hooks/post-receive
-- 
GNU gnutls



reply via email to

[Prev in Thread] Current Thread [Next in Thread]