diff options
author | Nikos Mavrogiannopoulos <nmav@crystal.(none)> | 2007-10-08 12:08:33 +0300 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@crystal.(none)> | 2007-10-08 12:08:33 +0300 |
commit | 1f24725c9a0b09e7a42ee18f2bb4c0fbac581b8f (patch) | |
tree | 984dd279834d1576512e1e8139b514305064a1d9 | |
parent | 38774ff46c11ed3b9aa5933279db2baf35ea3a53 (diff) | |
download | gnutls-1f24725c9a0b09e7a42ee18f2bb4c0fbac581b8f.tar.gz |
** Added capability to set a callback after the client hello is received
by the server in order to adjust parameters before the handshake.
** SRP was corrected to adhere (more) to the latest draft (published soon as RFC)
** Corrected bug which did not allow a server to run without supporting
certificates.
** Updated the DN parser which now prints wrongly decoded values as hex
strings.
-rw-r--r-- | NEWS | 13 | ||||
-rwxr-xr-x | doc/credentials/gnutls-http-serv | 2 | ||||
-rw-r--r-- | includes/gnutls/gnutls.h.in | 10 | ||||
-rw-r--r-- | lib/ext_srp.c | 23 | ||||
-rw-r--r-- | lib/gnutls_alert.c | 3 | ||||
-rw-r--r-- | lib/gnutls_errors.h | 1 | ||||
-rw-r--r-- | lib/gnutls_extensions.c | 4 | ||||
-rw-r--r-- | lib/gnutls_handshake.c | 96 | ||||
-rw-r--r-- | lib/gnutls_int.h | 9 | ||||
-rw-r--r-- | lib/gnutls_srp.c | 12 | ||||
-rw-r--r-- | lib/gnutls_state.c | 25 | ||||
-rw-r--r-- | lib/x509/common.c | 4 | ||||
-rw-r--r-- | lib/x509/dn.c | 5 | ||||
-rw-r--r-- | src/cli.c | 2 |
14 files changed, 104 insertions, 105 deletions
@@ -7,9 +7,22 @@ See the end for copying conditions. ** Removed all the xml related stubs and functions. +** Added capability to set a callback after the client hello is received +by the server in order to adjust parameters before the handshake. + +** SRP was corrected to adhere to the latest draft (published soon as RFC) + +** Corrected bug which did not allow a server to run without supporting +certificates. + +** Updated the DN parser which now prints wrongly decoded values as hex +strings. + ** API and ABI modifications: gnutls_x509_crt_to_xml: REMOVED gnutls_openpgp_key_to_xml: REMOVED +gnutls_srp_set_client_credentials_function: CHANGED +gnutls_handshake_set_post_client_hello_function: ADDED * Version 2.1.1 (released 2007-09-24) diff --git a/doc/credentials/gnutls-http-serv b/doc/credentials/gnutls-http-serv index 93e527a69e..5f5fcee3d4 100755 --- a/doc/credentials/gnutls-http-serv +++ b/doc/credentials/gnutls-http-serv @@ -1,6 +1,6 @@ #! /bin/sh -./gnutls-serv --http --x509certfile x509/cert.pem --x509keyfile x509/key.pem --x509cafile x509/ca.pem \ +../../src/gnutls-serv --http --x509certfile x509/cert.pem --x509keyfile x509/key.pem --x509cafile x509/ca.pem \ --x509dsacertfile x509/cert-dsa.pem --x509dsakeyfile x509/key-dsa.pem \ --srppasswd srp/tpasswd --srppasswdconf srp/tpasswd.conf \ --pgpkeyfile openpgp/sec.asc --pgpcertfile openpgp/pub.asc --pskpasswd psk/passwd.psk \ diff --git a/includes/gnutls/gnutls.h.in b/includes/gnutls/gnutls.h.in index ecfd261d97..381591c2d2 100644 --- a/includes/gnutls/gnutls.h.in +++ b/includes/gnutls/gnutls.h.in @@ -197,8 +197,7 @@ extern "C" GNUTLS_A_UNSUPPORTED_EXTENSION = 110, GNUTLS_A_CERTIFICATE_UNOBTAINABLE = 111, GNUTLS_A_UNRECOGNIZED_NAME = 112, - GNUTLS_A_UNKNOWN_SRP_USERNAME = 120, - GNUTLS_A_MISSING_SRP_USERNAME = 121, + GNUTLS_A_UNKNOWN_PSK_IDENTITY = 115, GNUTLS_A_INNER_APPLICATION_FAILURE = 208, GNUTLS_A_INNER_APPLICATION_VERIFICATION = 209 } gnutls_alert_description_t; @@ -600,6 +599,10 @@ extern "C" int gnutls_db_check_entry (gnutls_session_t session, gnutls_datum_t session_entry); + typedef int (*gnutls_handshake_post_client_hello_func)(gnutls_session_t); + void gnutls_handshake_set_post_client_hello_function(gnutls_session_t, + gnutls_handshake_post_client_hello_func); + void gnutls_handshake_set_max_packet_length (gnutls_session_t session, size_t max); @@ -911,8 +914,7 @@ extern "C" gnutls_srp_server_credentials_function * func); typedef int gnutls_srp_client_credentials_function (gnutls_session_t, - unsigned int, char **, - char **); + char **, char **); void gnutls_srp_set_client_credentials_function (gnutls_srp_client_credentials_t cred, diff --git a/lib/ext_srp.c b/lib/ext_srp.c index e8bd84e0c1..6350525679 100644 --- a/lib/ext_srp.c +++ b/lib/ext_srp.c @@ -40,15 +40,6 @@ _gnutls_srp_recv_params (gnutls_session_t session, const opaque * data, uint8_t len; ssize_t data_size = _data_size; - if (_gnutls_kx_priority (session, GNUTLS_KX_SRP) < 0 && - _gnutls_kx_priority (session, GNUTLS_KX_SRP_DSS) < 0 && - _gnutls_kx_priority (session, GNUTLS_KX_SRP_RSA) < 0) - { - /* algorithm was not allowed in this session - */ - return 0; - } - if (session->security_parameters.entity == GNUTLS_SERVER) { if (data_size > 0) @@ -117,19 +108,11 @@ _gnutls_srp_send_params (gnutls_session_t session, opaque * data, */ char *username = NULL, *password = NULL; - if (cred->get_function (session, - session->internals.handshake_restarted, - &username, &password) < 0 + if (cred->get_function (session, &username, &password) < 0 || username == NULL || password == NULL) { - - if (session->internals.handshake_restarted) - { - gnutls_assert (); - return GNUTLS_E_ILLEGAL_SRP_USERNAME; - } - - return 0; + gnutls_assert (); + return GNUTLS_E_ILLEGAL_SRP_USERNAME; } len = MIN (strlen (username), 255); diff --git a/lib/gnutls_alert.c b/lib/gnutls_alert.c index 449019b8d1..be2843e1b3 100644 --- a/lib/gnutls_alert.c +++ b/lib/gnutls_alert.c @@ -62,8 +62,7 @@ static const gnutls_alert_entry sup_alerts[] = { {GNUTLS_A_UNSUPPORTED_EXTENSION, "An unsupported extension was sent"}, {GNUTLS_A_UNRECOGNIZED_NAME, "The server name sent was not recognized"}, - {GNUTLS_A_UNKNOWN_SRP_USERNAME, "The SRP username is not known"}, - {GNUTLS_A_MISSING_SRP_USERNAME, "The SRP username was not sent"}, + {GNUTLS_A_UNKNOWN_PSK_IDENTITY, "The SRP/PSK username is missing or not known"}, {GNUTLS_A_INNER_APPLICATION_FAILURE, "Inner application negotiation failed"}, {GNUTLS_A_INNER_APPLICATION_VERIFICATION, diff --git a/lib/gnutls_errors.h b/lib/gnutls_errors.h index 46724708b0..4d98fa0a8c 100644 --- a/lib/gnutls_errors.h +++ b/lib/gnutls_errors.h @@ -25,7 +25,6 @@ #include <defines.h> #define GNUTLS_E_INT_RET_0 -1251 -#define GNUTLS_E_INT_HANDSHAKE_AGAIN -1252 #ifdef __FILE__ # ifdef __LINE__ diff --git a/lib/gnutls_extensions.c b/lib/gnutls_extensions.c index 20b1bbd414..4c54cbfb70 100644 --- a/lib/gnutls_extensions.c +++ b/lib/gnutls_extensions.c @@ -177,8 +177,8 @@ _gnutls_parse_extensions (gnutls_session_t session, const opaque * data, type = _gnutls_read_uint16 (&data[pos]); pos += 2; - _gnutls_debug_log ("EXT[%x]: Received extension '%s'\n", session, - _gnutls_extension_get_name (type)); + _gnutls_debug_log ("EXT[%x]: Received extension '%s/%d'\n", session, + _gnutls_extension_get_name (type),type); if ((ret = _gnutls_extension_list_check (session, type)) < 0) { diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c index f8d2724ff3..753bfe2d14 100644 --- a/lib/gnutls_handshake.c +++ b/lib/gnutls_handshake.c @@ -282,12 +282,12 @@ int _gnutls_read_client_hello (gnutls_session_t session, opaque * data, int datalen) { - uint8_t session_id_len, z; + uint8_t session_id_len; int pos = 0, ret; - uint16_t suite_size; + uint16_t suite_size, comp_size; gnutls_protocol_t version; int len = datalen; - opaque rnd[TLS_RANDOM_SIZE], *suite_ptr; + opaque rnd[TLS_RANDOM_SIZE], *suite_ptr, *comp_ptr; gnutls_protocol_t ver; if (session->internals.v2_hello != 0) @@ -376,20 +376,14 @@ _gnutls_read_client_hello (gnutls_session_t session, opaque * data, suite_ptr = &data[pos]; pos += suite_size; - /* Select an appropriate compression method + /* Point to the compression methods */ DECR_LEN (len, 1); - z = data[pos++]; /* z is the number of compression methods */ + comp_size = data[pos++]; /* z is the number of compression methods */ - DECR_LEN (len, z); - ret = _gnutls_server_select_comp_method (session, &data[pos], z); - pos += z; - - if (ret < 0) - { - gnutls_assert (); - return ret; - } + DECR_LEN (len, comp_size); + comp_ptr = &data[pos]; + pos += comp_size; /* Parse the extensions (if any) */ @@ -403,6 +397,16 @@ _gnutls_read_client_hello (gnutls_session_t session, opaque * data, } } + if (session->internals.user_hello_func != NULL) + { + ret = session->internals.user_hello_func( session); + if (ret < 0) + { + gnutls_assert(); + return ret; + } + } + /* select an appropriate cipher suite */ ret = _gnutls_server_select_suite (session, suite_ptr, suite_size); @@ -412,6 +416,14 @@ _gnutls_read_client_hello (gnutls_session_t session, opaque * data, return ret; } + /* select appropriate compression method */ + ret = _gnutls_server_select_comp_method (session, comp_ptr, comp_size); + if (ret < 0) + { + gnutls_assert (); + return ret; + } + return 0; } @@ -1115,17 +1127,6 @@ _gnutls_recv_handshake (gnutls_session_t session, uint8_t ** data, if (ret < 0) { - /* In SRP when expecting the server hello we may receive - * an alert instead. Do as the draft demands. - */ - if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED && - gnutls_alert_get (session) == GNUTLS_A_MISSING_SRP_USERNAME && - type == GNUTLS_HANDSHAKE_SERVER_HELLO) - { - gnutls_assert (); - return GNUTLS_E_INT_HANDSHAKE_AGAIN; - } - if (ret == GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET && optional == OPTIONAL_PACKET) { @@ -1839,19 +1840,19 @@ _gnutls_send_server_hello (gnutls_session_t session, int again) session->security_parameters.extensions.srp_username[0] == 0) { /* The peer didn't send a valid SRP extension with the - * SRP username. The draft requires that we send an - * alert and start the handshake again. + * SRP username. The draft requires that we send a fatal + * alert and abort. */ gnutls_assert (); - ret = gnutls_alert_send (session, GNUTLS_AL_WARNING, - GNUTLS_A_MISSING_SRP_USERNAME); + ret = gnutls_alert_send (session, GNUTLS_AL_FATAL, + GNUTLS_A_UNKNOWN_PSK_IDENTITY); if (ret < 0) { gnutls_assert (); return ret; } - return GNUTLS_E_INT_HANDSHAKE_AGAIN; + return GNUTLS_E_ILLEGAL_SRP_USERNAME; } } #endif @@ -2217,21 +2218,8 @@ gnutls_handshake (gnutls_session_t session) return 0; } -/* Here if GNUTLS_E_INT_HANDSHAKE_AGAIN is received we go to - * restart. This works because this error code may only be - * received on the first 2 handshake packets. If for some reason - * this changes we should return GNUTLS_E_AGAIN. - */ #define IMED_RET( str, ret) do { \ if (ret < 0) { \ - if (ret == GNUTLS_E_INT_HANDSHAKE_AGAIN && \ - session->internals.handshake_restarted == 1) \ - ret = GNUTLS_E_INTERNAL_ERROR; \ - if (ret == GNUTLS_E_INT_HANDSHAKE_AGAIN) { \ - STATE = STATE0; \ - session->internals.handshake_restarted = 1; \ - goto restart; \ - } \ if (gnutls_error_is_fatal(ret)==0) return ret; \ gnutls_assert(); \ ERR( str, ret); \ @@ -2263,7 +2251,6 @@ _gnutls_handshake_client (gnutls_session_t session) session_id_size, buf, sizeof (buf))); #endif -restart: switch (STATE) { @@ -2491,8 +2478,6 @@ _gnutls_handshake_server (gnutls_session_t session) { int ret = 0; -restart: - switch (STATE) { case STATE0: @@ -2594,8 +2579,6 @@ _gnutls_handshake_common (gnutls_session_t session) { int ret = 0; -restart: - /* send and recv the change cipher spec and finished messages */ if ((session->internals.resumed == RESUME_TRUE && session->security_parameters.entity == GNUTLS_CLIENT) @@ -2801,11 +2784,11 @@ _gnutls_remove_unwanted_ciphersuites (gnutls_session_t session, int ret = 0; cipher_suite_st *newSuite, cs; int newSuiteSize = 0, i; - gnutls_certificate_credentials_t x509_cred; + gnutls_certificate_credentials_t cert_cred; gnutls_kx_algorithm_t kx; int server = session->security_parameters.entity == GNUTLS_SERVER ? 1 : 0; - gnutls_kx_algorithm_t *alg; - int alg_size; + gnutls_kx_algorithm_t *alg = NULL; + int alg_size = 0; /* if we should use a specific certificate, * we should remove all algorithms that are not supported @@ -2813,22 +2796,23 @@ _gnutls_remove_unwanted_ciphersuites (gnutls_session_t session, * method (CERTIFICATE). */ - x509_cred = + cert_cred = (gnutls_certificate_credentials_t) _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL); - /* if x509_cred==NULL we should remove all X509 ciphersuites + /* If there are certificate credentials, find an appropriate certificate + * or disable them; */ - if (session->security_parameters.entity == GNUTLS_SERVER - && x509_cred != NULL) + && cert_cred != NULL) { ret = _gnutls_server_select_cert (session, requested_pk_algo); if (ret < 0) { gnutls_assert (); - return ret; + _gnutls_x509_log("Could not find an appropriate certificate: %s\n", gnutls_strerror(ret)); + cert_cred = NULL; } } diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index 1c9f10e5f5..2cff4d1eda 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -549,6 +549,10 @@ typedef struct gnutls_db_retr_func db_retrieve_func; gnutls_db_remove_func db_remove_func; void *db_ptr; + + /* post client hello callback (server side only) + */ + gnutls_handshake_post_client_hello_func user_hello_func; /* Holds the record size requested by the * user. @@ -612,11 +616,6 @@ typedef struct char *srp_username; char *srp_password; - /* This is only set in SRP, when the handshake is - * restarted if an username is not found. - */ - int handshake_restarted; - /* Here we cache the DH or RSA parameters got from the * credentials structure, or from a callback. That is to * minimize external calls. diff --git a/lib/gnutls_srp.c b/lib/gnutls_srp.c index 7a54d2d382..99678a7035 100644 --- a/lib/gnutls_srp.c +++ b/lib/gnutls_srp.c @@ -612,21 +612,15 @@ gnutls_srp_set_server_credentials_function (gnutls_srp_server_credentials_t * This function can be used to set a callback to retrieve the username and * password for client SRP authentication. * The callback's function form is: - * int (*callback)(gnutls_session_t, unsigned int times, char** username, + * int (*callback)(gnutls_session_t, char** username, * char** password); * * The @username and @password must be allocated using gnutls_malloc(). - * @times will be 0 the first time called, and 1 the second. * @username and @password should be ASCII strings or UTF-8 strings * prepared using the "SASLprep" profile of "stringprep". * - * The callback function will be called once or twice per handshake. - * The first time called, is before the ciphersuite is negotiated. - * At that time if the callback returns a negative error code, - * the callback will be called again if SRP has been - * negotiated. This uses a special TLS-SRP idiom in order to avoid - * asking the user for SRP password and username if the server does - * not support SRP. + * The callback function will be called once per handshake before the + * initial hello message is sent. * * The callback should not return a negative error code the second * time called, since the handshake procedure will be aborted. diff --git a/lib/gnutls_state.c b/lib/gnutls_state.c index 7e07e6773d..4bbbbace46 100644 --- a/lib/gnutls_state.c +++ b/lib/gnutls_state.c @@ -209,8 +209,6 @@ _gnutls_handshake_internal_state_clear (gnutls_session_t session) session->internals.last_handshake_in = -1; session->internals.last_handshake_out = -1; - session->internals.handshake_restarted = 0; - session->internals.resumable = RESUME_TRUE; _gnutls_free_datum (&session->internals.recv_buffer); @@ -1209,3 +1207,26 @@ _gnutls_rsa_pms_set_version (gnutls_session_t session, session->internals.rsa_pms_version[0] = major; session->internals.rsa_pms_version[1] = minor; } + +/** + * gnutls_handshake_set_post_client_hello_function - This function will a callback to be called after the client hello is received + * @res: is a gnutls_anon_server_credentials_t structure + * @func: is the function to be called + * + * This function will set a callback to be called after the client hello + * has been received (callback valid in server side only). This allows the + * server to adjust settings based on received extensions. + * + * Those settings could be ciphersuites, requesting certificate, or anything + * else except for version negotiation (this is done before the hello message + * is parsed). + * + * This callback must return 0 on success or a gnutls error code to + * terminate the handshake. + * + **/ +void gnutls_handshake_set_post_client_hello_function( gnutls_session_t session, + gnutls_handshake_post_client_hello_func func) +{ + session->internals.user_hello_func = func; +} diff --git a/lib/x509/common.c b/lib/x509/common.c index e1b7f7a2d6..515dcfe8d0 100644 --- a/lib/x509/common.c +++ b/lib/x509/common.c @@ -183,6 +183,7 @@ _gnutls_x509_oid_data2string (const char *oid, void *value, const char *ANAME = NULL; int CHOICE = -1, len = -1, result; ASN1_TYPE tmpasn = ASN1_TYPE_EMPTY; + char asn1_err[MAX_ERROR_DESCRIPTION_SIZE] = ""; if (value == NULL || value_size <= 0 || res_size == NULL) { @@ -217,9 +218,10 @@ _gnutls_x509_oid_data2string (const char *oid, void *value, } if ((result = - asn1_der_decoding (&tmpasn, value, value_size, NULL)) != ASN1_SUCCESS) + asn1_der_decoding (&tmpasn, value, value_size, asn1_err)) != ASN1_SUCCESS) { gnutls_assert (); + _gnutls_x509_log("asn1_der_decoding: %s:%s\n", str, asn1_err); asn1_delete_structure (&tmpasn); return _gnutls_asn2err (result); } diff --git a/lib/x509/dn.c b/lib/x509/dn.c index d891763500..33927cdac2 100644 --- a/lib/x509/dn.c +++ b/lib/x509/dn.c @@ -261,12 +261,15 @@ _gnutls_x509_parse_dn (ASN1_TYPE asn1_struct, STR_APPEND (ldap_desc); STR_APPEND ("="); + result = 0; + if (printable) result = _gnutls_x509_oid_data2string (oid, value2, len, string, &sizeof_string); - else + + if (!printable || result < 0) result = _gnutls_x509_data2hex (value2, len, string, &sizeof_string); @@ -1004,7 +1004,7 @@ do_handshake (socket_st * socket) static int srp_username_callback (gnutls_session_t session, - unsigned int times, char **username, char **password) + char **username, char **password) { if (srp_username == NULL || srp_passwd == NULL) { |