diff options
Diffstat (limited to 'lib/ext_dnsname.c')
-rw-r--r-- | lib/ext_dnsname.c | 126 |
1 files changed, 107 insertions, 19 deletions
diff --git a/lib/ext_dnsname.c b/lib/ext_dnsname.c index e65106098a..3760fe29a4 100644 --- a/lib/ext_dnsname.c +++ b/lib/ext_dnsname.c @@ -24,21 +24,38 @@ #include "gnutls_errors.h" #include "gnutls_num.h" -int _gnutls_dnsname_recv_params( GNUTLS_STATE state, const opaque* data, int data_size) { +/* This file should have been called ext_name_ind.c + * + * In case of a server: if a DNSNAME extension type is received then it stores + * into the state the value of DNSNAME. The server may use gnutls_ext_get_name_ind(), + * in order to access it. + * + * In case of a client: If a proper DNSNAME extension type is found in the state then + * it sends the extension to the peer. + * + */ + +int _gnutls_name_ind_recv_params( GNUTLS_STATE state, const opaque* data, int data_size) { uint16 len; if (state->security_parameters.entity == GNUTLS_SERVER) { if (data_size > 0) { - 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; - } - /* 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 */ + len = READuint16( data); + if (len > data_size || len >= MAX_DNSNAME_SIZE || len < 3) { + gnutls_assert(); + return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; + } + + switch(data[2]) { + case 0: + if (sizeof( state->security_parameters.extensions.name.dnsname) > len-2) { + state->security_parameters.extensions.name.type = GNUTLS_DNSNAME; + /* note that dnsname is in UTF-8 + * format. + */ + memcpy( state->security_parameters.extensions.name.dnsname, &data[3], len-1); + state->security_parameters.extensions.name.dnsname[len-1]=0; /* null terminated */ + break; + } } } } @@ -48,17 +65,88 @@ int _gnutls_dnsname_recv_params( GNUTLS_STATE state, const opaque* data, int dat /* returns data_size or a negative number on failure * data is allocated localy */ -int _gnutls_dnsname_send_params( GNUTLS_STATE state, opaque** data) { +int _gnutls_name_ind_send_params( GNUTLS_STATE state, opaque** data) { uint16 len; /* this function sends the client extension data (dnsname) */ if (state->security_parameters.entity == GNUTLS_CLIENT) { - 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; + switch (state->security_parameters.extensions.name.type) { + case GNUTLS_DNSNAME: + if ( (len = strlen(state->security_parameters.extensions.name.dnsname)) > 0) { /* send dnsname */ + (*data) = gnutls_malloc(len+3); /* hold the size and the type also */ + + WRITEuint16( len+1, *data); + (*data)[2] = 0; + memcpy( &(*data)[3], state->security_parameters.extensions.name.dnsname, len); + return len + 3; + } + return 0; + default: + return GNUTLS_E_UNIMPLEMENTED_FEATURE; } } - return 0; + return GNUTLS_E_UNKNOWN_ERROR; +} + +/** + * gnutls_ext_get_name_ind - Used to get the name indicator send by a client + * @state: is a &GNUTLS_STATE structure. + * @ind: is a name indicator type + * + * This function will allow you to get the name indication (if any), + * a client has sent. The name indication may be any of the enumeration + * GNUTLS_NAME_IND. + * + * If 'ind' is GNUTLS_DNSNAME, then this function is to be used by servers + * that support virtual hosting. + * The client may give the server the dnsname they connected to. + * + * The return value depends on the 'ind' type. In case of GNUTLS_DNSNAME, + * it is a null terminated string. If no name indication was given (maybe the client + * does not support this extension) this function returns NULL. + * + **/ +const void* gnutls_ext_get_name_ind( GNUTLS_STATE state, GNUTLS_NAME_IND ind) { + if (state->security_parameters.entity==GNUTLS_CLIENT) return NULL; + + switch( ind) { + case GNUTLS_DNSNAME: + if ( state->security_parameters.extensions.name.dnsname[0] == 0 || + state->security_parameters.extensions.name.type!=ind) return NULL; + return state->security_parameters.extensions.name.dnsname; + } + + return NULL; +} + +/** + * gnutls_ext_set_name_ind - Used to set a name indicator to be sent as an extension + * @state: is a &GNUTLS_STATE structure. + * @name: is a null terminated string that contains the dns name. + * @ind: specified the indicator type + * + * 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. + * + * The value of 'name' depends on the 'ind' type. In case of GNUTLS_DNSNAME, + * a null terminated string is expected. + * + **/ +int gnutls_ext_set_name_ind( GNUTLS_STATE state, GNUTLS_NAME_IND ind, const void* name) { +const char* dnsname; + + if (state->security_parameters.entity==GNUTLS_SERVER) return GNUTLS_E_UNIMPLEMENTED_FEATURE; + state->security_parameters.extensions.name.type = ind; + + switch(ind) { + case GNUTLS_DNSNAME: + dnsname = name; + if (strlen( dnsname) >= MAX_DNSNAME_SIZE) return GNUTLS_E_MEMORY_ERROR; + strcpy( state->security_parameters.extensions.name.dnsname, dnsname); + return 0; + } + + return GNUTLS_E_UNIMPLEMENTED_FEATURE; } |