summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@crystal.(none)>2007-10-08 12:08:33 +0300
committerNikos Mavrogiannopoulos <nmav@crystal.(none)>2007-10-08 12:08:33 +0300
commit1f24725c9a0b09e7a42ee18f2bb4c0fbac581b8f (patch)
tree984dd279834d1576512e1e8139b514305064a1d9
parent38774ff46c11ed3b9aa5933279db2baf35ea3a53 (diff)
downloadgnutls-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--NEWS13
-rwxr-xr-xdoc/credentials/gnutls-http-serv2
-rw-r--r--includes/gnutls/gnutls.h.in10
-rw-r--r--lib/ext_srp.c23
-rw-r--r--lib/gnutls_alert.c3
-rw-r--r--lib/gnutls_errors.h1
-rw-r--r--lib/gnutls_extensions.c4
-rw-r--r--lib/gnutls_handshake.c96
-rw-r--r--lib/gnutls_int.h9
-rw-r--r--lib/gnutls_srp.c12
-rw-r--r--lib/gnutls_state.c25
-rw-r--r--lib/x509/common.c4
-rw-r--r--lib/x509/dn.c5
-rw-r--r--src/cli.c2
14 files changed, 104 insertions, 105 deletions
diff --git a/NEWS b/NEWS
index 8343324fca..3828fa68a1 100644
--- a/NEWS
+++ b/NEWS
@@ -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);
diff --git a/src/cli.c b/src/cli.c
index b0ce847071..177f9e76e8 100644
--- a/src/cli.c
+++ b/src/cli.c
@@ -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)
{