diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2002-01-20 13:02:58 +0000 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2002-01-20 13:02:58 +0000 |
commit | a40e1270d8354e24f63a9ba1d9a25c5ba19f434f (patch) | |
tree | 75fd5f7f57c84a2896c27b084885d4a80adb60c8 | |
parent | 1f80606b1da479e4c5664904b95afd3ab9792129 (diff) | |
download | gnutls-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.tex | 3 | ||||
-rw-r--r-- | lib/gnutls_handshake.c | 40 | ||||
-rw-r--r-- | lib/gnutls_record.c | 13 | ||||
-rw-r--r-- | src/cli.c | 4 | ||||
-rw-r--r-- | src/serv.c | 7 |
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) { @@ -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); |