From: Nikos Mavrogiannopoulos Date: Sun, 24 Jun 2001 21:42:34 +0000 (+0000) Subject: added support for DNSNAME extension (draft-ietf-tls-extensions) X-Git-Tag: gnutls_0_1_9~68 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=1ea07d330580eaead30b9e852361972ee8e05515;p=thirdparty%2Fgnutls.git added support for DNSNAME extension (draft-ietf-tls-extensions) --- diff --git a/NEWS b/NEWS index 43c72b480d..59440bcf27 100644 --- a/NEWS +++ b/NEWS @@ -1,6 +1,7 @@ Version 0.1.5 - Corrected bug(s) in ChangeCipherSpec packet (fixes renegotiate) - SRP is updated to conform to the newest draft. +- Added support for DNSNAME extension. Version 0.1.4 (22/06/2001) - Corrected (srp) base64 encoding. diff --git a/lib/ext_dnsname.c b/lib/ext_dnsname.c index 4002796889..e65106098a 100644 --- a/lib/ext_dnsname.c +++ b/lib/ext_dnsname.c @@ -22,19 +22,23 @@ #include "gnutls_auth_int.h" #include "auth_x509.h" #include "gnutls_errors.h" +#include "gnutls_num.h" int _gnutls_dnsname_recv_params( GNUTLS_STATE state, const opaque* data, int data_size) { - uint8 len; + uint16 len; if (state->security_parameters.entity == GNUTLS_SERVER) { if (data_size > 0) { - if (sizeof( state->gnutls_key->dnsname) > data_size) { - len = data[0]; - if (len > data_size) { + if (sizeof( state->security_parameters.extensions.dnsname) > data_size) { + len = READuint16( data); + if (len > data_size || len >= MAX_DNSNAME_SIZE) { gnutls_assert(); return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } - memcpy( state->gnutls_key->dnsname, &data[1], len); - state->gnutls_key->dnsname[len]=0; /* null terminated */ + /* note that dnsname is in UTF-8 + * format. + */ + memcpy( state->security_parameters.extensions.dnsname, &data[2], len); + state->security_parameters.extensions.dnsname[len]=0; /* null terminated */ } } } @@ -45,15 +49,15 @@ int _gnutls_dnsname_recv_params( GNUTLS_STATE state, const opaque* data, int dat * data is allocated localy */ int _gnutls_dnsname_send_params( GNUTLS_STATE state, opaque** data) { - uint8 len; + uint16 len; /* this function sends the client extension data (dnsname) */ if (state->security_parameters.entity == GNUTLS_CLIENT) { - if ( (len = strlen(state->gnutls_key->dnsname)) > 0) { /* send dnsname */ - (*data) = gnutls_malloc(len+1); /* hold the size also */ - (*data)[0] = len; - memcpy( &(*data)[1], state->gnutls_key->dnsname, len); - return len + 1; + if ( (len = strlen(state->security_parameters.extensions.dnsname)) > 0) { /* send dnsname */ + (*data) = gnutls_malloc(len+2); /* hold the size also */ + WRITEuint16( len, *data); + memcpy( &(*data)[2], state->security_parameters.extensions.dnsname, len); + return len + 2; } } return 0; diff --git a/lib/gnutls.h.in b/lib/gnutls.h.in index 73de6ca5f4..75e0f71a77 100644 --- a/lib/gnutls.h.in +++ b/lib/gnutls.h.in @@ -130,6 +130,12 @@ int gnutls_clear_creds( GNUTLS_STATE state); int gnutls_set_cred( GNUTLS_STATE, CredType type, void* cred); const void* gnutls_get_auth_info( GNUTLS_STATE); +/* A null terminated string containing the dnsname. + * This will only exist if the client supports the dnsname + * TLS extension. (draft-ietf-tls-extensions) + */ +const char* gnutls_ext_get_dnsname( GNUTLS_STATE); + /* Credential structures for SRP - used in gnutls_set_cred(); */ typedef struct { char* username; diff --git a/lib/gnutls_constate.c b/lib/gnutls_constate.c index c11f7610a4..e7498f46d2 100644 --- a/lib/gnutls_constate.c +++ b/lib/gnutls_constate.c @@ -142,41 +142,28 @@ int _gnutls_set_write_keys(GNUTLS_STATE state) return _gnutls_set_keys( state, hash_size, IV_size, key_size); } - -static void _gnutls_cpy_read_security_parameters( SecurityParameters * dst, SecurityParameters* src) { - dst->entity = src->entity; - dst->kx_algorithm = src->kx_algorithm; - - memcpy( &dst->current_cipher_suite, &src->current_cipher_suite, sizeof(GNUTLS_CipherSuite)); +#define CPY_COMMON dst->entity = src->entity; \ + dst->kx_algorithm = src->kx_algorithm; \ + memcpy( &dst->current_cipher_suite, &src->current_cipher_suite, sizeof(GNUTLS_CipherSuite)); \ + memcpy( dst->master_secret, src->master_secret, TLS_MASTER_SIZE); \ + memcpy( dst->client_random, src->client_random, TLS_RANDOM_SIZE); \ + memcpy( dst->server_random, src->server_random, TLS_RANDOM_SIZE); \ + memcpy( dst->session_id, src->session_id, TLS_MAX_SESSION_ID_SIZE); \ + dst->session_id_size = src->session_id_size; \ + dst->timestamp = src->timestamp; \ + memcpy( &dst->extensions, &src->extensions, sizeof(TLSExtensions)); - memcpy( dst->master_secret, src->master_secret, TLS_MASTER_SIZE); - memcpy( dst->client_random, src->client_random, TLS_RANDOM_SIZE); - memcpy( dst->server_random, src->server_random, TLS_RANDOM_SIZE); - - memcpy( dst->session_id, src->session_id, TLS_MAX_SESSION_ID_SIZE); +static void _gnutls_cpy_read_security_parameters( SecurityParameters * dst, SecurityParameters* src) { + CPY_COMMON; - dst->session_id_size = src->session_id_size; - dst->timestamp = src->timestamp; - dst->read_bulk_cipher_algorithm = src->read_bulk_cipher_algorithm; dst->read_mac_algorithm = src->read_mac_algorithm; dst->read_compression_algorithm = src->read_compression_algorithm; } static void _gnutls_cpy_write_security_parameters( SecurityParameters * dst, SecurityParameters* src) { - dst->entity = src->entity; - dst->kx_algorithm = src->kx_algorithm; - - memcpy( &dst->current_cipher_suite, &src->current_cipher_suite, sizeof(GNUTLS_CipherSuite)); - - memcpy( dst->master_secret, src->master_secret, TLS_MASTER_SIZE); - memcpy( dst->client_random, src->client_random, TLS_RANDOM_SIZE); - memcpy( dst->server_random, src->server_random, TLS_RANDOM_SIZE); - - memcpy( dst->session_id, src->session_id, TLS_MAX_SESSION_ID_SIZE); - dst->session_id_size = src->session_id_size; - dst->timestamp = src->timestamp; - + CPY_COMMON; + dst->write_bulk_cipher_algorithm = src->write_bulk_cipher_algorithm; dst->write_mac_algorithm = src->write_mac_algorithm; dst->write_compression_algorithm = src->write_compression_algorithm; diff --git a/lib/gnutls_extensions.c b/lib/gnutls_extensions.c index ef3a8de0b9..7a68efe619 100644 --- a/lib/gnutls_extensions.c +++ b/lib/gnutls_extensions.c @@ -38,8 +38,8 @@ typedef struct { #define MAX_EXT 20 /* maximum supported extension */ static gnutls_extension_entry extensions[] = { - GNUTLS_EXTENSION_ENTRY(GNUTLS_EXTENSION_SRP, _gnutls_srp_recv_params, _gnutls_srp_send_params), - GNUTLS_EXTENSION_ENTRY(GNUTLS_EXTENSION_DNSNAME, _gnutls_dnsname_recv_params, _gnutls_dnsname_send_params), + GNUTLS_EXTENSION_ENTRY( GNUTLS_EXTENSION_SRP, _gnutls_srp_recv_params, _gnutls_srp_send_params), + GNUTLS_EXTENSION_ENTRY( GNUTLS_EXTENSION_DNSNAME, _gnutls_dnsname_recv_params, _gnutls_dnsname_send_params), {0} }; @@ -171,3 +171,41 @@ int (*ext_func_send)( GNUTLS_STATE, opaque**); return size; } + +/** + * gnutls_ext_get_dnsname - Used to get the dnsname a client connected to + * @state: is a &GNUTLS_STATE structure. + * + * This function is to be used by servers that support virtual hosting. + * The client may give the server the dnsname they connected to. + * if no name was given this function returns NULL. + * + **/ +const char* gnutls_ext_get_dnsname( GNUTLS_STATE state) { + if (state->security_parameters.entity==GNUTLS_CLIENT) return NULL; + + if (strlen( state->security_parameters.extensions.dnsname) == 0) return NULL; + + return state->security_parameters.extensions.dnsname; +} + +/** + * gnutls_ext_set_dnsname - Used to set the dnsname as an extension + * @state: is a &GNUTLS_STATE structure. + * @dnsname: is a null terminated string that contains the dns name. + * + * This function is to be used by clients that want to inform + * ( via a TLS extension mechanism) the server of the name they + * connected to. This should be used by clients that connect + * to servers that do virtual hosting. + **/ +int gnutls_ext_set_dnsname( GNUTLS_STATE state, char* dnsname) { + + if (state->security_parameters.entity==GNUTLS_SERVER) return GNUTLS_E_UNIMPLEMENTED_FEATURE; + + if (strlen( dnsname) >= MAX_DNSNAME_SIZE) return GNUTLS_E_MEMORY_ERROR; + + strcpy( state->security_parameters.extensions.dnsname, dnsname); + + return 0; +} diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c index 35e67bb6d5..8bba1ec225 100644 --- a/lib/gnutls_handshake.c +++ b/lib/gnutls_handshake.c @@ -1746,12 +1746,12 @@ int _gnutls_remove_unwanted_ciphersuites(GNUTLS_STATE state, */ cert = NULL; - if (state->gnutls_key->dnsname[0] != 0) { + if (state->security_parameters.extensions.dnsname[0] != 0) { cert = (gnutls_cert *) _gnutls_find_cert(x509_cred->cert_list, x509_cred->ncerts, - state->gnutls_key-> - dnsname); + state->security_parameters. + extensions.dnsname); } if (cert == NULL) { /* if no such cert, use the first in the list diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index 83c8f36b4d..d6f100947c 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -45,6 +45,8 @@ #define TLS_MAX_SESSION_ID_SIZE 32 #define TLS_MASTER_SIZE 48 +#define MAX_DNSNAME_SIZE 256 + /* the default for TCP */ #define DEFAULT_LOWAT 1 @@ -118,7 +120,7 @@ typedef struct { /* STATE */ typedef enum ConnectionEnd { GNUTLS_SERVER=1, GNUTLS_CLIENT } ConnectionEnd; typedef enum BulkCipherAlgorithm { GNUTLS_NULL_CIPHER=1, GNUTLS_ARCFOUR, GNUTLS_3DES_CBC, GNUTLS_RIJNDAEL_CBC, GNUTLS_TWOFISH_CBC, GNUTLS_RIJNDAEL256_CBC } BulkCipherAlgorithm; -typedef enum Extensions { GNUTLS_EXTENSION_SRP=7, GNUTLS_EXTENSION_DNSNAME } Extensions; +typedef enum Extensions { GNUTLS_EXTENSION_DNSNAME=0, GNUTLS_EXTENSION_SRP=6 } Extensions; typedef enum KXAlgorithm { GNUTLS_KX_RSA=1, GNUTLS_KX_DHE_DSS, GNUTLS_KX_DHE_RSA, GNUTLS_KX_DH_DSS, GNUTLS_KX_DH_RSA, GNUTLS_KX_DH_ANON, GNUTLS_KX_SRP } KXAlgorithm; typedef enum CredType { GNUTLS_X509PKI=1, GNUTLS_ANON, GNUTLS_SRP } CredType; typedef enum CipherType { CIPHER_STREAM, CIPHER_BLOCK } CipherType; @@ -167,7 +169,8 @@ typedef struct { /* this is used to hold the peers authentication data */ void* auth_info; - int auth_info_size; /* needed in order to store to db for restoring */ + int auth_info_size; /* needed in order to store to db for restoring + */ uint8 crypt_algo; /* These are needed in RSA and DH signature calculation @@ -175,7 +178,6 @@ typedef struct { opaque server_random[TLS_RANDOM_SIZE]; opaque client_random[TLS_RANDOM_SIZE]; ProtocolVersion version; - opaque dnsname[256]; AUTH_CRED* cred; /* used to specify keys/certificates etc */ } GNUTLS_KEY_A; @@ -192,6 +194,14 @@ typedef struct { uint8 CipherSuite[2]; } GNUTLS_CipherSuite; +/* This structure holds parameters got from TLS extension + * mechanism. (some extensions may hold parameters in AUTH_INFO + * structures instead - see SRP). + */ +typedef struct { + opaque dnsname[MAX_DNSNAME_SIZE]; +} TLSExtensions; + /* This structure and AUTH_INFO, are stored in the resume database, * and are restored, in case of resume. * Holds all the required parameters to resume the current @@ -223,6 +233,7 @@ typedef struct { opaque session_id[TLS_MAX_SESSION_ID_SIZE]; uint8 session_id_size; time_t timestamp; + TLSExtensions extensions; } SecurityParameters; /* This structure holds the generated keys diff --git a/src/cli.c b/src/cli.c index e69b5178b4..f28936083d 100644 --- a/src/cli.c +++ b/src/cli.c @@ -144,7 +144,8 @@ int main(int argc, char** argv) gnutls_set_cred( state, GNUTLS_ANON, NULL); gnutls_set_cred( state, GNUTLS_SRP, &cred); gnutls_set_cred( state, GNUTLS_X509PKI, &xcred); - + gnutls_ext_set_dnsname( state, "hello.server.org"); + gnutls_set_mac_priority( state, GNUTLS_MAC_SHA, GNUTLS_MAC_MD5, 0); ret = gnutls_handshake(sd, state); @@ -195,6 +196,8 @@ int main(int argc, char** argv) gnutls_set_cred( state, GNUTLS_SRP, &cred); gnutls_set_cred( state, GNUTLS_X509PKI, &xcred); + gnutls_ext_set_dnsname( state, "hello.server.org"); + gnutls_set_mac_priority( state, GNUTLS_MAC_SHA, GNUTLS_MAC_MD5, 0); #ifdef RESUME diff --git a/src/serv.c b/src/serv.c index ac68f1632d..8505508cb3 100644 --- a/src/serv.c +++ b/src/serv.c @@ -115,6 +115,9 @@ void print_info(GNUTLS_STATE state) printf("%.2X", sesid[i]); printf("\n"); + printf("- DNSNAME: "); + printf("%s\n", gnutls_ext_get_dnsname(state)); + /* print srp specific data */ if (gnutls_get_current_kx(state) == GNUTLS_KX_SRP) { srp_info = gnutls_get_auth_info(state); @@ -171,6 +174,14 @@ void peer_print_info(int cd, GNUTLS_STATE state) sprintf(tmp2, "%.2X", sesid[i]); sprintf(tmp2, "

\n"); + /* if the client supports dnsname extension then + * print the hostname he connected to. + */ + if (gnutls_ext_get_dnsname(state)!=NULL) { + printf("\n

DNSNAME: "); + printf("%s

\n", gnutls_ext_get_dnsname(state)); + } + /* print srp specific data */ if (gnutls_get_current_kx(state) == GNUTLS_KX_SRP) { srp_info = gnutls_get_auth_info(state);