summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2002-01-20 13:02:58 +0000
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2002-01-20 13:02:58 +0000
commita40e1270d8354e24f63a9ba1d9a25c5ba19f434f (patch)
tree75fd5f7f57c84a2896c27b084885d4a80adb60c8
parent1f80606b1da479e4c5664904b95afd3ab9792129 (diff)
downloadgnutls-a40e1270d8354e24f63a9ba1d9a25c5ba19f434f.tar.gz
Now a server in a case of rehandshake can continue normaly
if the handshake request is ignored by the client.
-rw-r--r--doc/tex/errors.tex3
-rw-r--r--lib/gnutls_handshake.c40
-rw-r--r--lib/gnutls_record.c13
-rw-r--r--src/cli.c4
-rw-r--r--src/serv.c7
5 files changed, 47 insertions, 20 deletions
diff --git a/doc/tex/errors.tex b/doc/tex/errors.tex
index 449c2c6810..d751c4a598 100644
--- a/doc/tex/errors.tex
+++ b/doc/tex/errors.tex
@@ -13,7 +13,8 @@ may warn about something (ie a warning alert was received), or
indicate the some action has to be taken. This is the case with
the error code GNUTLS\_E\_REHANDSHAKE returned by
\hyperref{gnutls\_read()}{gnutls\_read() (see Section }{)}{gnutls_read}.
-This error code requires a full handshake to be performed again, or an alert to be sent.
+This error code indicates that the server requests a rehandshake. The client
+may ignore this request, or may reply with an alert.
You can test if an error code is a fatal one by using the
\hyperref{gnutls\_error\_is\_fatal()}{gnutls\_error\_is\_fatal() (see Section }{)}{gnutls_error_is_fatal}.
\par
diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c
index e5be490f90..914d3b9857 100644
--- a/lib/gnutls_handshake.c
+++ b/lib/gnutls_handshake.c
@@ -39,6 +39,7 @@
#include "gnutls_cert.h"
#include "gnutls_constate.h"
#include <gnutls_record.h>
+#include <gnutls_alert.h>
#ifdef HANDSHAKE_DEBUG
#define ERR(x, y) _gnutls_log( "GNUTLS Error: %s (%d)\n", x,y)
@@ -1653,7 +1654,7 @@ int gnutls_rehandshake(GNUTLS_STATE state)
/* only server sends that handshake packet */
if (state->security_parameters.entity == GNUTLS_CLIENT)
- return GNUTLS_E_UNIMPLEMENTED_FEATURE;
+ return GNUTLS_E_INVALID_REQUEST;
ret =
_gnutls_send_empty_handshake(state, GNUTLS_HELLO_REQUEST,
@@ -1669,13 +1670,23 @@ int gnutls_rehandshake(GNUTLS_STATE state)
return 0;
}
+static int _gnutls_abort_handshake( GNUTLS_STATE state, int ret) {
+ if ( ((ret==GNUTLS_E_WARNING_ALERT_RECEIVED) &&
+ ( gnutls_alert_get_last(state) == GNUTLS_A_NO_RENEGOTIATION))
+ || ret==GNUTLS_E_GOT_APPLICATION_DATA)
+ return 0;
+
+ /* this doesn't matter */
+ return GNUTLS_E_UNKNOWN_ERROR;
+}
+
/**
* gnutls_handshake - This the main function in the handshake protocol.
* @state: is a a &GNUTLS_STATE structure.
*
* This function does the handshake of the TLS/SSL protocol,
- * and initializes the TLS connection. Here the identity of the peer
- * is checked automatically.
+ * and initializes the TLS connection.
+ *
* This function will fail if any problem is encountered,
* and will return a negative error code. In case of a client,
* if it has been asked to resume a session, but the server didn't, then
@@ -1685,6 +1696,12 @@ int gnutls_rehandshake(GNUTLS_STATE state)
* GNUTLS_E_INTERRUPTED. In that case you may resume the handshake
* (call this function again, until it returns ok)
*
+ * If this function is called by a server after a rehandshake request
+ * then GNUTLS_E_GOT_APPLICATION_DATA or GNUTLS_E_WARNING_ALERT_RECEIVED
+ * may be returned. Note that these are non fatal errors, only in the
+ * case of a rehandshake. In that case they mean that the client
+ * rejected the rehandshake request.
+ *
**/
int gnutls_handshake(GNUTLS_STATE state)
{
@@ -1695,14 +1712,23 @@ int gnutls_handshake(GNUTLS_STATE state)
} else {
ret = gnutls_handshake_server(state);
}
- if (ret < 0)
+ if (ret < 0) {
+ /* In the case of a rehandshake abort
+ * we should reset the handshake's state
+ */
+ if (_gnutls_abort_handshake( state, ret) == 0)
+ STATE = STATE0;
return ret;
-
+ }
+
ret = gnutls_handshake_common(state);
- if (ret < 0)
+ if (ret < 0) {
+ if (_gnutls_abort_handshake( state, ret) == 0)
+ STATE = STATE0;
return ret;
-
+ }
+
STATE = STATE0;
_gnutls_handshake_io_buffer_clear(state);
diff --git a/lib/gnutls_record.c b/lib/gnutls_record.c
index 15b080f478..0c09e1ba16 100644
--- a/lib/gnutls_record.c
+++ b/lib/gnutls_record.c
@@ -621,8 +621,6 @@ ssize_t gnutls_recv_int( GNUTLS_STATE state, ContentType type, HandshakeType hty
int ret, ret2;
int header_size;
- begin:
-
header_size = RECORD_HEADER_SIZE;
ret = 0;
@@ -859,10 +857,7 @@ ssize_t gnutls_recv_int( GNUTLS_STATE state, ContentType type, HandshakeType hty
gnutls_assert();
gnutls_free(tmpdata);
- goto begin; /* ok we received the packet,
- * and now we should get the one
- * we expected.
- */
+ return GNUTLS_E_GOT_APPLICATION_DATA;
break;
case GNUTLS_HANDSHAKE:
@@ -1067,9 +1062,9 @@ ssize_t gnutls_write( GNUTLS_STATE state, const void *data, size_t sizeofdata) {
* Also returns the number of bytes received, zero on EOF, but
* a negative error code in case of an error.
*
- * If this function returns GNUTLS_E_REHANDSHAKE, then you must
- * either send an alert containing NO_RENEGOTIATION, or perform a
- * handshake. (only a client may receive this message)
+ * If this function returns GNUTLS_E_REHANDSHAKE, then you may
+ * ignore this message, send an alert containing NO_RENEGOTIATION,
+ * or perform a handshake again. (only a client may receive this message)
*
**/
ssize_t gnutls_read( GNUTLS_STATE state, void *data, size_t sizeofdata) {
diff --git a/src/cli.c b/src/cli.c
index 2dd05d3872..c4919bde3a 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -82,7 +82,7 @@ static int cert_callback( GNUTLS_STATE state, const gnutls_datum *client_certs,
}
const int protocol_priority[] = { GNUTLS_TLS1, GNUTLS_SSL3, 0 };
-const int kx_priority[] = { GNUTLS_KX_RSA, GNUTLS_KX_DHE_RSA, GNUTLS_KX_SRP, GNUTLS_KX_ANON_DH, 0 };
+const int kx_priority[] = { GNUTLS_KX_DHE_RSA, GNUTLS_KX_RSA, GNUTLS_KX_SRP, GNUTLS_KX_ANON_DH, 0 };
const int cipher_priority[] = { GNUTLS_CIPHER_RIJNDAEL_128_CBC, GNUTLS_CIPHER_3DES_CBC, GNUTLS_CIPHER_ARCFOUR, 0};
const int comp_priority[] = { GNUTLS_COMP_ZLIB, GNUTLS_COMP_NULL, 0 };
const int mac_priority[] = { GNUTLS_MAC_SHA, GNUTLS_MAC_MD5, 0 };
@@ -309,9 +309,11 @@ int main(int argc, char** argv)
if (ret==GNUTLS_E_WARNING_ALERT_RECEIVED || ret==GNUTLS_E_FATAL_ALERT_RECEIVED)
printf("* Received alert [%d]\n", gnutls_alert_get_last(state));
if (ret==GNUTLS_E_REHANDSHAKE) {
+ /* gnutls_alert_send( state, GNUTLS_AL_WARNING, GNUTLS_A_NO_RENEGOTIATION); */
do {
ret = gnutls_handshake( state);
} while( ret==GNUTLS_E_AGAIN || ret==GNUTLS_E_INTERRUPTED);
+
if (ret==0) printf("* Rehandshake was performed\n");
else {
printf("* Rehandshake Failed [%d]\n", ret);
diff --git a/src/serv.c b/src/serv.c
index 5a18c786e9..e3554f8f62 100644
--- a/src/serv.c
+++ b/src/serv.c
@@ -207,9 +207,12 @@ int read_request( GNUTLS_STATE state, char *data, int data_size, int rnl)
}
void check_alert( GNUTLS_STATE state, int ret) {
+int last_alert;
+
if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED || ret == GNUTLS_E_FATAL_ALERT_RECEIVED) {
- ret = gnutls_alert_get_last(state);
- if (ret == GNUTLS_A_NO_RENEGOTIATION)
+ last_alert = gnutls_alert_get_last(state);
+ if (last_alert == GNUTLS_A_NO_RENEGOTIATION &&
+ ret == GNUTLS_E_WARNING_ALERT_RECEIVED)
printf("* Received NO_RENEGOTIATION alert. Client Does not support renegotiation.\n");
else
printf("* Received alert '%d'.\n", ret);