diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2001-12-04 16:03:19 +0000 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2001-12-04 16:03:19 +0000 |
commit | eb5ea263bc6597de2b78ee5e5f8ca2a4137f0eca (patch) | |
tree | fe6b091a9dcc3446b53f557a96ef6e0aa1c22a35 | |
parent | f4fcde5c4eb58ea592cf5e3f0cc41534a7e73b46 (diff) | |
download | gnutls-eb5ea263bc6597de2b78ee5e5f8ca2a4137f0eca.tar.gz |
now the peer's certificate list is stored into auth info structure (instead
of the certificate).
several other cleanups.
-rw-r--r-- | configure.in | 26 | ||||
-rw-r--r-- | lib/auth_dhe_rsa.c | 113 | ||||
-rw-r--r-- | lib/auth_x509.c | 305 | ||||
-rw-r--r-- | lib/auth_x509.h | 8 | ||||
-rw-r--r-- | lib/gnutls.h.in | 1 | ||||
-rw-r--r-- | lib/gnutls_auth.c | 14 | ||||
-rw-r--r-- | lib/gnutls_cert.c | 23 | ||||
-rw-r--r-- | lib/gnutls_cert.h | 7 | ||||
-rw-r--r-- | lib/gnutls_errors.c | 1 | ||||
-rw-r--r-- | lib/gnutls_errors_int.h | 3 | ||||
-rw-r--r-- | lib/gnutls_int.h | 1 | ||||
-rw-r--r-- | lib/gnutls_kx.c | 8 | ||||
-rw-r--r-- | lib/gnutls_record.c | 2 | ||||
-rw-r--r-- | lib/gnutls_session_pack.c | 142 | ||||
-rw-r--r-- | lib/gnutls_ui.c | 142 | ||||
-rw-r--r-- | lib/gnutls_ui.h | 4 | ||||
-rw-r--r-- | lib/x509_extensions.c | 351 | ||||
-rw-r--r-- | lib/x509_extensions.h | 1 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/cli.c | 14 | ||||
-rw-r--r-- | src/common.h | 14 | ||||
-rw-r--r-- | src/port.h | 2 | ||||
-rw-r--r-- | src/serv.c | 13 |
23 files changed, 746 insertions, 451 deletions
diff --git a/configure.in b/configure.in index 14a98c92bf..34e7121f2f 100644 --- a/configure.in +++ b/configure.in @@ -261,19 +261,29 @@ AC_SUBST( DEFINE_SIZE_T) ]) -AC_CHECK_TYPE(time_t,, -AC_DEFINE(NO_TIME_T), +AC_CHECK_TYPE(time_t, + DEFINE_TIME_T="#include <time.h>" + AC_SUBST( DEFINE_TIME_T) + , + AC_CHECK_TYPE(time_t, + DEFINE_TIME_T="#include <sys/time.h>" + AC_SUBST( DEFINE_TIME_T) + , + DEFINE_TIME_T="typedef unsigned int time_t;" + AC_SUBST( DEFINE_TIME_T) + AC_DEFINE(NO_TIME_T), + [ + #include <sys/time.h> + ] + ) +, [ -#ifdef HAVE_TIME_H -# include <time.h> -#endif -#ifdef HAVE_SYS_TIME_H -# include <sys/time.h> -#endif + #include <time.h> ] ) + AC_C_BIGENDIAN AC_MSG_RESULT([*** diff --git a/lib/auth_dhe_rsa.c b/lib/auth_dhe_rsa.c index d6f7b8291c..dea2635e39 100644 --- a/lib/auth_dhe_rsa.c +++ b/lib/auth_dhe_rsa.c @@ -79,7 +79,10 @@ static int gen_dhe_rsa_server_kx(GNUTLS_STATE state, opaque ** data) } /* find the appropriate certificate */ - if ((ret=_gnutls_find_apr_cert( state, &apr_cert_list, &apr_cert_list_length, &apr_pkey))<0) { + if ((ret = + _gnutls_find_apr_cert(state, &apr_cert_list, + &apr_cert_list_length, + &apr_pkey)) < 0) { gnutls_assert(); return ret; } @@ -90,7 +93,7 @@ static int gen_dhe_rsa_server_kx(GNUTLS_STATE state, opaque ** data) return GNUTLS_E_MEMORY_ERROR; } - if ( state->gnutls_key->auth_info==NULL) { + if (state->gnutls_key->auth_info == NULL) { state->gnutls_key->auth_info = gnutls_calloc(1, sizeof(X509PKI_AUTH_INFO_INT)); if (state->gnutls_key->auth_info == NULL) @@ -105,13 +108,14 @@ static int gen_dhe_rsa_server_kx(GNUTLS_STATE state, opaque ** data) state->gnutls_key->auth_info_type = GNUTLS_X509PKI; } else - if (gnutls_get_auth_type( state) != state->gnutls_key->auth_info_type) { - gnutls_assert(); - return GNUTLS_E_INVALID_REQUEST; - } + if (gnutls_get_auth_type(state) != + state->gnutls_key->auth_info_type) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } info = state->gnutls_key->auth_info; - + X = gnutls_calc_dh_secret(&x, g, p); if (X == NULL) { _gnutls_mpi_release(&g); @@ -160,28 +164,29 @@ static int gen_dhe_rsa_server_kx(GNUTLS_STATE state, opaque ** data) if (apr_pkey != NULL) { if ((ret = - _gnutls_generate_sig_params( - state, &apr_cert_list[0], apr_pkey, &ddata, &signature)) < 0) { + _gnutls_generate_sig_params(state, &apr_cert_list[0], + apr_pkey, &ddata, + &signature)) < 0) { gnutls_assert(); - gnutls_free( *data); + gnutls_free(*data); return ret; } } else { gnutls_assert(); - return data_size; /* do not put a signature - ILLEGAL! */ + return data_size; /* do not put a signature - ILLEGAL! */ } - *data = gnutls_realloc( *data, data_size+signature.size+2); - if (*data==NULL) { - gnutls_free_datum( &signature); + *data = gnutls_realloc(*data, data_size + signature.size + 2); + if (*data == NULL) { + gnutls_free_datum(&signature); gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; } - - WRITEdatum16( &(*data)[data_size], signature); - data_size += signature.size+2; - gnutls_free_datum( &signature); + WRITEdatum16(&(*data)[data_size], signature); + data_size += signature.size + 2; + + gnutls_free_datum(&signature); return data_size; } @@ -194,21 +199,21 @@ static int gen_dhe_rsa_client_kx(GNUTLS_STATE state, opaque ** data) X = gnutls_calc_dh_secret(&x, state->gnutls_key->client_g, state->gnutls_key->client_p); - if (X==NULL || x==NULL) { + if (X == NULL || x == NULL) { gnutls_assert(); - _gnutls_mpi_release( &x); - _gnutls_mpi_release( &X); + _gnutls_mpi_release(&x); + _gnutls_mpi_release(&X); return GNUTLS_E_MEMORY_ERROR; } - + gcry_mpi_print(GCRYMPI_FMT_USG, NULL, &n_X, X); (*data) = gnutls_malloc(n_X + 2); if (*data == NULL) { - _gnutls_mpi_release( &x); - _gnutls_mpi_release( &X); + _gnutls_mpi_release(&x); + _gnutls_mpi_release(&X); return GNUTLS_E_MEMORY_ERROR; } - + gcry_mpi_print(GCRYMPI_FMT_USG, &(*data)[2], &n_X, X); _gnutls_mpi_release(&X); @@ -220,7 +225,7 @@ static int gen_dhe_rsa_client_kx(GNUTLS_STATE state, opaque ** data) state->gnutls_key->client_p); _gnutls_mpi_release(&x); - if (state->gnutls_key->KEY==NULL) { + if (state->gnutls_key->KEY == NULL) { gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; } @@ -230,7 +235,7 @@ static int gen_dhe_rsa_client_kx(GNUTLS_STATE state, opaque ** data) _gnutls_mpi_release(&state->gnutls_key->client_p); _gnutls_mpi_release(&state->gnutls_key->client_g); - ret = _gnutls_generate_key( state->gnutls_key); + ret = _gnutls_generate_key(state->gnutls_key); _gnutls_mpi_release(&state->gnutls_key->KEY); if (ret < 0) { @@ -251,6 +256,14 @@ static int proc_dhe_rsa_server_kx(GNUTLS_STATE state, opaque * data, int i, sigsize; gnutls_datum vparams, signature; int ret; + X509PKI_AUTH_INFO info = state->gnutls_key->auth_info; + gnutls_cert peer_cert; + + if (info == NULL || info->ncerts==0) { + gnutls_assert(); + /* we need this in order to get peer's certificate */ + return GNUTLS_E_UNKNOWN_ERROR; + } i = 0; n_p = READuint16(&data[i]); @@ -287,39 +300,51 @@ static int proc_dhe_rsa_server_kx(GNUTLS_STATE state, opaque * data, _n_p = n_p; if (_gnutls_mpi_scan(&state->gnutls_key->client_Y, - GCRYMPI_FMT_USG, data_Y, &_n_Y) != 0) { + GCRYMPI_FMT_USG, data_Y, &_n_Y) != 0) { gnutls_assert(); return GNUTLS_E_MPI_SCAN_FAILED; } if (_gnutls_mpi_scan(&state->gnutls_key->client_g, - GCRYMPI_FMT_USG, data_g, &_n_g) != 0) { + GCRYMPI_FMT_USG, data_g, &_n_g) != 0) { gnutls_assert(); return GNUTLS_E_MPI_SCAN_FAILED; } if (_gnutls_mpi_scan(&state->gnutls_key->client_p, - GCRYMPI_FMT_USG, data_p, &_n_p) != 0) { + GCRYMPI_FMT_USG, data_p, &_n_p) != 0) { gnutls_assert(); return GNUTLS_E_MPI_SCAN_FAILED; } /* VERIFY SIGNATURE */ - + vparams.size = n_Y + n_p + n_g + 6; vparams.data = data; - if (data_size-vparams.size-2 <= 0) { /* check if the peer sent enough data */ + if (data_size - vparams.size - 2 <= 0) { /* check if the peer sent enough data */ gnutls_assert(); return GNUTLS_E_UNEXPECTED_PACKET_LENGTH; } - - sigsize = READuint16( &data[vparams.size]); - signature.data = &data[vparams.size+2]; - signature.size = GMIN(data_size-vparams.size-2, sigsize); - ret = _gnutls_verify_sig_params( state, &state->gnutls_internals.peer_cert, &vparams, &signature); - if (ret<0) { + sigsize = READuint16(&data[vparams.size]); + signature.data = &data[vparams.size + 2]; + signature.size = GMIN(data_size - vparams.size - 2, sigsize); + + if ((ret = + _gnutls_cert2gnutlsCert( &peer_cert, + info->raw_certificate_list[0])) < 0) { + gnutls_assert(); + return ret; + } + + ret = + _gnutls_verify_sig_params(state, + &peer_cert, + &vparams, &signature); + + gnutls_free_cert( peer_cert); + if (ret < 0) { gnutls_assert(); return ret; } @@ -349,16 +374,16 @@ static int proc_dhe_rsa_client_kx(GNUTLS_STATE state, opaque * data, _n_Y = n_Y; if (_gnutls_mpi_scan(&state->gnutls_key->client_Y, - GCRYMPI_FMT_USG, &data[2], &_n_Y)) { + GCRYMPI_FMT_USG, &data[2], &_n_Y)) { gnutls_assert(); return GNUTLS_E_MPI_SCAN_FAILED; } g = gnutls_get_dh_params(&p, bits); - if (g==NULL || p==NULL) { + if (g == NULL || p == NULL) { gnutls_assert(); - _gnutls_mpi_release( &g); - _gnutls_mpi_release( &p); + _gnutls_mpi_release(&g); + _gnutls_mpi_release(&p); return GNUTLS_E_MEMORY_ERROR; } @@ -368,7 +393,7 @@ static int proc_dhe_rsa_client_kx(GNUTLS_STATE state, opaque * data, _gnutls_mpi_release(&g); _gnutls_mpi_release(&p); - if (state->gnutls_key->KEY==NULL) { + if (state->gnutls_key->KEY == NULL) { return GNUTLS_E_MEMORY_ERROR; } @@ -376,7 +401,7 @@ static int proc_dhe_rsa_client_kx(GNUTLS_STATE state, opaque * data, _gnutls_mpi_release(&state->gnutls_key->client_Y); _gnutls_mpi_release(&state->gnutls_key->dh_secret); - ret = _gnutls_generate_key( state->gnutls_key); + ret = _gnutls_generate_key(state->gnutls_key); _gnutls_mpi_release(&state->gnutls_key->KEY); if (ret < 0) { diff --git a/lib/auth_x509.c b/lib/auth_x509.c index cf3e22c292..95b366b4fc 100644 --- a/lib/auth_x509.c +++ b/lib/auth_x509.c @@ -36,36 +36,52 @@ #include <x509_verify.h> #include <gnutls_sig.h> #include <ext_dnsname.h> +#include <x509_extensions.h> /* Copies data from a internal certificate struct (gnutls_cert) to * exported certificate struct (X509PKI_AUTH_INFO) */ -int _gnutls_copy_x509_client_auth_info( X509PKI_AUTH_INFO info, gnutls_cert* cert, CertificateStatus verify) { +int _gnutls_copy_x509_auth_info( X509PKI_AUTH_INFO info, gnutls_cert* cert, int ncerts, CertificateStatus verify) { /* Copy peer's information to AUTH_INFO */ -int ret; +int ret, i, j; info->peer_certificate_status = verify; - info->peer_certificate_version = cert->version; + if (ncerts==0) { + info->raw_certificate_list = NULL; + info->ncerts = 0; + return 0; + } - if ( cert->subjectAltDNSName[0]!=0) - strcpy( info->subjectAltDNSName, cert->subjectAltDNSName); - - info->keyUsage = cert->keyUsage; - - info->peer_certificate_expiration_time = cert->expiration_time; - info->peer_certificate_activation_time = cert->activation_time; + info->raw_certificate_list = gnutls_calloc( 1, sizeof(gnutls_datum)*ncerts); + if (info->raw_certificate_list==NULL) { + gnutls_assert(); + return GNUTLS_E_MEMORY_ERROR; + } - if (cert->raw.size > 0) { - ret = gnutls_set_datum( &info->raw_certificate, cert->raw.data, cert->raw.size); - if ( ret < 0) { - gnutls_assert(); - return ret; + for (i=0;i<ncerts;i++) { + if (cert->raw.size > 0) { + ret = gnutls_set_datum( &info->raw_certificate_list[i], cert[i].raw.data, cert[i].raw.size); + if ( ret < 0) { + gnutls_assert(); + goto clear; + } } } - + info->ncerts = ncerts; + return 0; + + clear: + + for (j=0;j<i;j++) + gnutls_free_datum( &info->raw_certificate_list[j]); + + gnutls_free( info->raw_certificate_list); + info->raw_certificate_list = NULL; + + return ret; } typedef struct { @@ -615,17 +631,6 @@ int _gnutls_proc_x509_server_certificate(GNUTLS_STATE state, opaque * data, int gnutls_free(peer_certificate_list); return ret; } - if (j==0) { /* Copy the first certificate in the chain - peer's certificate - * into the peer_cert. This is needed in order to access these - * parameters later. - */ - if ((ret = _gnutls_cert2gnutlsCert(&state->gnutls_internals.peer_cert, tmp)) < 0) { - gnutls_assert(); - CLEAR_CERTS; - gnutls_free(peer_certificate_list); - return ret; - } - } p += len; i -= len + 3; @@ -656,7 +661,7 @@ int _gnutls_proc_x509_server_certificate(GNUTLS_STATE state, opaque * data, int /* keep the PK algorithm */ state->gnutls_internals.peer_pk_algorithm = peer_certificate_list[0].subject_pk_algorithm; - if ( (ret = _gnutls_copy_x509_client_auth_info(info, &peer_certificate_list[0], verify)) < 0) { + if ( (ret = _gnutls_copy_x509_auth_info(info, peer_certificate_list, peer_certificate_list_size, verify)) < 0) { gnutls_assert(); return ret; } @@ -804,6 +809,14 @@ int size, ret; int dsize = data_size; opaque* pdata = data; gnutls_datum sig; +X509PKI_AUTH_INFO info = state->gnutls_key->auth_info; +gnutls_cert peer_cert; + + if (info == NULL || info->ncerts==0) { + gnutls_assert(); + /* we need this in order to get peer's certificate */ + return GNUTLS_E_UNKNOWN_ERROR; + } DECR_LEN(dsize, 2); size = READuint16( pdata); @@ -817,10 +830,19 @@ gnutls_datum sig; sig.data = pdata; sig.size = size; - if ( (ret=_gnutls_verify_sig_hdata( state, &state->gnutls_internals.peer_cert, &sig, data_size+HANDSHAKE_HEADER_SIZE))<0) { + if ((ret = + _gnutls_cert2gnutlsCert( &peer_cert, + info->raw_certificate_list[0])) < 0) { + gnutls_assert(); + return ret; + } + + if ( (ret=_gnutls_verify_sig_hdata( state, &peer_cert, &sig, data_size+HANDSHAKE_HEADER_SIZE))<0) { gnutls_assert(); + gnutls_free_cert( peer_cert); return ret; } + gnutls_free_cert( peer_cert); return 0; } @@ -974,7 +996,7 @@ int gnutls_x509pki_get_peer_dn(GNUTLS_STATE state, gnutls_DN * ret) } - result = asn1_get_der(c2, info->raw_certificate.data, info->raw_certificate.size); + result = asn1_get_der(c2, info->raw_certificate_list[0].data, info->raw_certificate_list[0].size); if (result != ASN_OK) { /* couldn't decode DER */ #ifdef DEBUG @@ -1031,7 +1053,7 @@ int gnutls_x509pki_get_issuer_dn(GNUTLS_STATE state, gnutls_DN * ret) return GNUTLS_E_ASN1_ERROR; } - result = asn1_get_der(c2, info->raw_certificate.data, info->raw_certificate.size); + result = asn1_get_der(c2, info->raw_certificate_list[0].data, info->raw_certificate_list[0].size); if (result != ASN_OK) { /* couldn't decode DER */ #ifdef DEBUG @@ -1054,3 +1076,224 @@ int gnutls_x509pki_get_issuer_dn(GNUTLS_STATE state, gnutls_DN * ret) return 0; } + +/** + * gnutls_x509pki_get_subject_dns_name - This function returns the peer's dns name, if any + * @state: is a gnutls state + * @ret: is the place where dns name will be copied to + * @ret_size: holds the size of ret. + * + * This function will return the peer's alternative name (the dns part of it). + * This is specified in X509v3 Certificate Extensions. + * GNUTLS will only return the dnsName of the Alternative name, or a negative + * error code. + * Returns GNUTLS_E_MEMORY_ERROR if ret_size is not enough to hold dns name, + * or the size of dns name if everything was ok. + * + * If the certificate does not have a DNS name then returns GNUTLS_E_DATA_NOT_AVAILABLE; + * + **/ +int gnutls_x509pki_get_subject_dns_name(GNUTLS_STATE state, char* ret, int *ret_size) +{ + X509PKI_AUTH_INFO info; + int result; + gnutls_datum dnsname; + + CHECK_AUTH(GNUTLS_X509PKI, GNUTLS_E_INVALID_REQUEST); + + info = _gnutls_get_auth_info(state); + if (info == NULL) + return GNUTLS_E_INVALID_REQUEST; + + + memset(ret, 0, *ret_size); + + if ((result = + _gnutls_get_extension( &info->raw_certificate_list[0], "2 5 29 17", &dnsname)) < 0) { + gnutls_assert(); + return result; + } + + if (dnsname.size==0) { + return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; + } + + if ( *ret_size > dnsname.size) { + *ret_size = dnsname.size; + strcpy( ret, dnsname.data); + gnutls_free_datum( &dnsname); + } else { + *ret_size = dnsname.size; + gnutls_free_datum( &dnsname); + return GNUTLS_E_MEMORY_ERROR; + } + + return *ret_size; +} + +/** + * gnutls_x509pki_get_peer_certificate_activation_time - This function returns the peer's certificate activation time + * @state: is a gnutls state + * + * This function will return the peer's certificate activation time in UNIX time + * (ie seconds since 00:00:00 UTC January 1, 1970). + * Returns a (time_t) -1 in case of an error. + * + **/ +time_t gnutls_x509pki_get_peer_certificate_activation_time(GNUTLS_STATE + state) +{ + X509PKI_AUTH_INFO info; + node_asn *c2; + int result; + time_t ret; + + CHECK_AUTH(GNUTLS_X509PKI, -1); + + info = _gnutls_get_auth_info(state); + if (info == NULL) + return -1; + + if (asn1_create_structure + (_gnutls_get_pkix(), "PKIX1Implicit88.Certificate", &c2, + "certificate2") + != ASN_OK) { + gnutls_assert(); + return -1; + } + + result = asn1_get_der(c2, info->raw_certificate_list[0].data, info->raw_certificate_list[0].size); + if (result != ASN_OK) { + /* couldn't decode DER */ +#ifdef DEBUG + _gnutls_log("Decoding error %d\n", result); +#endif + gnutls_assert(); + return -1; + } + + ret = _gnutls_get_time(c2, "certificate2", "notBefore"); + + asn1_delete_structure(c2); + + return ret; +} + +/** + * gnutls_x509pki_get_peer_certificate_expiration_time - This function returns the peer's certificate expiration time + * @state: is a gnutls state + * + * This function will return the peer's certificate expiration time in UNIX time + * (ie seconds since 00:00:00 UTC January 1, 1970). + * Returns a (time_t) -1 in case of an error. + * + **/ +time_t gnutls_x509pki_get_peer_certificate_expiration_time(GNUTLS_STATE + state) +{ + X509PKI_AUTH_INFO info; + node_asn *c2; + int result; + time_t ret; + + CHECK_AUTH(GNUTLS_X509PKI, -1); + + info = _gnutls_get_auth_info(state); + if (info == NULL) + return -1; + + if (asn1_create_structure + (_gnutls_get_pkix(), "PKIX1Implicit88.Certificate", &c2, + "certificate2") + != ASN_OK) { + gnutls_assert(); + return -1; + } + + result = asn1_get_der(c2, info->raw_certificate_list[0].data, info->raw_certificate_list[0].size); + if (result != ASN_OK) { + /* couldn't decode DER */ +#ifdef DEBUG + _gnutls_log("Decoding error %d\n", result); +#endif + gnutls_assert(); + return -1; + } + + ret = _gnutls_get_time(c2, "certificate2", "notAfter"); + + asn1_delete_structure(c2); + + return ret; +} + +/** + * gnutls_x509pki_get_peer_certificate_version - This function returns the peer's certificate version + * @state: is a gnutls state + * + * This function will return the peer's certificate version (1, 2, 3). This is obtained by the X509 Certificate + * Version field. If the certificate is invalid then version will be zero. + * Returns a negative value in case of an error. + * + **/ +int gnutls_x509pki_get_peer_certificate_version(GNUTLS_STATE state) +{ + X509PKI_AUTH_INFO info; + node_asn *c2; + int result; + + CHECK_AUTH(GNUTLS_X509PKI, GNUTLS_E_INVALID_REQUEST); + + info = _gnutls_get_auth_info(state); + if (info == NULL) + return GNUTLS_E_INVALID_REQUEST; + + if (asn1_create_structure + (_gnutls_get_pkix(), "PKIX1Implicit88.Certificate", &c2, + "certificate2") + != ASN_OK) { + gnutls_assert(); + return GNUTLS_E_ASN1_ERROR; + } + + result = asn1_get_der(c2, info->raw_certificate_list[0].data, info->raw_certificate_list[0].size); + if (result != ASN_OK) { + /* couldn't decode DER */ +#ifdef DEBUG + _gnutls_log("Decoding error %d\n", result); +#endif + gnutls_assert(); + return GNUTLS_E_ASN1_PARSING_ERROR; + } + + result = _gnutls_get_version(c2, "certificate2"); + + asn1_delete_structure(c2); + + return result; + +} + +/** + * gnutls_x509pki_get_peer_certificate_status - This function returns the peer's certificate status + * @state: is a gnutls state + * + * This function will return the peer's certificate status (TRUSTED, EXPIRED etc.). This is the output + * of the certificate verification function. However you must also check the peer's name in order + * to check if the verified certificate belongs to the actual peer. + * Returns GNUTLS_CERT_NONE in case of an error, or if no certificate was sent. + * + **/ +CertificateStatus gnutls_x509pki_get_peer_certificate_status(GNUTLS_STATE + state) +{ + X509PKI_AUTH_INFO info; + + CHECK_AUTH(GNUTLS_X509PKI, GNUTLS_CERT_NONE); + + info = _gnutls_get_auth_info(state); + if (info == NULL) + return GNUTLS_CERT_NONE; + + return info->peer_certificate_status; +} diff --git a/lib/auth_x509.h b/lib/auth_x509.h index 27385a5705..774b8e7df9 100644 --- a/lib/auth_x509.h +++ b/lib/auth_x509.h @@ -45,18 +45,14 @@ typedef struct { typedef struct X509PKI_AUTH_INFO_INT { CertificateStatus peer_certificate_status; - int peer_certificate_version; - time_t peer_certificate_activation_time; - time_t peer_certificate_expiration_time; - char subjectAltDNSName[X509_CN_SIZE]; - unsigned char keyUsage; int certificate_requested; /* if the peer requested certificate * this is non zero; */ int dh_bits; /* bits of the DH (if DHE_RSA is used) */ - gnutls_datum raw_certificate; /* holds the raw certificate of the + gnutls_datum* raw_certificate_list; /* holds the raw certificate of the * peer. */ + int ncerts; /* holds the size of the list above */ } *X509PKI_AUTH_INFO; typedef struct X509PKI_AUTH_INFO_INT X509PKI_AUTH_INFO_INT; diff --git a/lib/gnutls.h.in b/lib/gnutls.h.in index 835ac16f5e..f055616e03 100644 --- a/lib/gnutls.h.in +++ b/lib/gnutls.h.in @@ -28,6 +28,7 @@ extern "C" { #define LIBGNUTLS_VERSION "@VERSION@" @DEFINE_SIZE_T@ +@DEFINE_TIME_T@ #define GNUTLS_AES GNUTLS_RIJNDAEL diff --git a/lib/gnutls_auth.c b/lib/gnutls_auth.c index 8af9a04696..a0267b3118 100644 --- a/lib/gnutls_auth.c +++ b/lib/gnutls_auth.c @@ -205,13 +205,21 @@ void _gnutls_free_auth_info( GNUTLS_STATE state) { break; case GNUTLS_X509PKI: { + int i; X509PKI_AUTH_INFO info = _gnutls_get_auth_info(state); - if (info==NULL) break; - gnutls_free( info->raw_certificate.data); - + if (info==NULL) break; + for (i=0;i<info->ncerts;i++) { + gnutls_free( info->raw_certificate_list[0].data); + } + + gnutls_free( info->raw_certificate_list); + info->raw_certificate_list = NULL; + info->ncerts = 0; } + + break; default: return; diff --git a/lib/gnutls_cert.c b/lib/gnutls_cert.c index 789b54b7f8..c91b5a6b15 100644 --- a/lib/gnutls_cert.c +++ b/lib/gnutls_cert.c @@ -751,7 +751,7 @@ int _gnutls_get_name_type(node_asn * rasn, char *root, gnutls_DN * dn) #define MAX_TIME 1024 -static time_t _gnutls_get_time(node_asn * c2, char *root, char *when) +time_t _gnutls_get_time(node_asn * c2, char *root, char *when) { opaque ttime[MAX_TIME]; char name[1024]; @@ -798,7 +798,7 @@ static time_t _gnutls_get_time(node_asn * c2, char *root, char *when) return ctime; } -static int _gnutls_get_version(node_asn * c2, char *root) +int _gnutls_get_version(node_asn * c2, char *root) { opaque gversion[5]; char name[1024]; @@ -831,6 +831,8 @@ int _gnutls_cert2gnutlsCert(gnutls_cert * gCert, gnutls_datum derCert) opaque str[MAX_X509_CERT_SIZE]; int len = sizeof(str); + memset( gCert, 0, sizeof(gnutls_cert)); + gCert->valid = 1; if (asn1_create_structure @@ -911,7 +913,7 @@ int _gnutls_cert2gnutlsCert(gnutls_cert * gCert, gnutls_datum derCert) gCert->subject_pk_algorithm = GNUTLS_PK_UNKNOWN; } - + len = sizeof(gCert->signature); result = asn1_read_value @@ -926,8 +928,12 @@ int _gnutls_cert2gnutlsCert(gnutls_cert * gCert, gnutls_datum derCert) gCert->signature_size = len; - memset(&gCert->subjectAltDNSName, 0, - sizeof(gCert->subjectAltDNSName)); + gCert->expiration_time = + _gnutls_get_time(c2, "certificate2", "notAfter"); + gCert->activation_time = + _gnutls_get_time(c2, "certificate2", "notBefore"); + gCert->version = _gnutls_get_version(c2, "certificate2"); + if ((result = _gnutls_get_ext_type(c2, "certificate2.tbsCertificate.extensions", @@ -937,13 +943,6 @@ int _gnutls_cert2gnutlsCert(gnutls_cert * gCert, gnutls_datum derCert) return result; } - gCert->expiration_time = - _gnutls_get_time(c2, "certificate2", "notAfter"); - gCert->activation_time = - _gnutls_get_time(c2, "certificate2", "notBefore"); - - gCert->version = _gnutls_get_version(c2, "certificate2"); - asn1_delete_structure(c2); if (gnutls_set_datum(&gCert->raw, derCert.data, derCert.size) < 0) { diff --git a/lib/gnutls_cert.h b/lib/gnutls_cert.h index 2b9365e02b..1e3013bc4d 100644 --- a/lib/gnutls_cert.h +++ b/lib/gnutls_cert.h @@ -7,14 +7,11 @@ #define MAX_PARAMS_SIZE 2 /* ok for RSA */ typedef struct gnutls_cert { - MPI params[MAX_PARAMS_SIZE]; /* the size of params depends on the public + MPI params[MAX_PARAMS_SIZE]; /* the size of params depends on the public * key algorithm */ PKAlgorithm subject_pk_algorithm; - opaque subjectAltDNSName[X509_CN_SIZE]; - int subjectAltDNSName_size; - opaque signature[1024]; int signature_size; @@ -58,5 +55,7 @@ void _gnutls_int2str(int k, char* data); int _gnutls_get_name_type( node_asn *rasn, char *root, gnutls_DN * dn); void gnutls_free_cert(gnutls_cert cert); int _gnutls_check_x509_key_usage( const gnutls_cert * cert, KXAlgorithm alg); +int _gnutls_get_version(node_asn * c2, char *root); +time_t _gnutls_get_time(node_asn * c2, char *root, char *when); #endif diff --git a/lib/gnutls_errors.c b/lib/gnutls_errors.c index f8c80e266b..2da20177c9 100644 --- a/lib/gnutls_errors.c +++ b/lib/gnutls_errors.c @@ -73,6 +73,7 @@ static gnutls_error_entry error_algorithms[] = { GNUTLS_ERROR_ENTRY( GNUTLS_E_EXPIRED, 1), GNUTLS_ERROR_ENTRY( GNUTLS_E_HASH_FAILED, 1), GNUTLS_ERROR_ENTRY( GNUTLS_E_PARSING_ERROR, 1), + GNUTLS_ERROR_ENTRY( GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE, 0), GNUTLS_ERROR_ENTRY( GNUTLS_E_PULL_ERROR, 1), GNUTLS_ERROR_ENTRY( GNUTLS_E_PUSH_ERROR, 1), GNUTLS_ERROR_ENTRY( GNUTLS_E_NO_CERTIFICATE_FOUND, 1), diff --git a/lib/gnutls_errors_int.h b/lib/gnutls_errors_int.h index 4426100b5c..c1962a28d0 100644 --- a/lib/gnutls_errors_int.h +++ b/lib/gnutls_errors_int.h @@ -48,7 +48,6 @@ #define GNUTLS_E_PK_SIGNATURE_FAILED -46 #define GNUTLS_E_X509_UNSUPPORTED_CRITICAL_EXTENSION -47 #define GNUTLS_E_X509_KEY_USAGE_VIOLATION -48 -#define GNUTLS_E_PKCS1_WRONG_PAD -48 #define GNUTLS_E_NO_CERTIFICATE_FOUND -49 #define GNUTLS_E_INVALID_PARAMETERS -50 #define GNUTLS_E_INVALID_REQUEST -51 @@ -56,5 +55,7 @@ #define GNUTLS_E_PUSH_ERROR -53 #define GNUTLS_E_PULL_ERROR -54 #define GNUTLS_E_ILLEGAL_PARAMETER -55 +#define GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE -56 +#define GNUTLS_E_PKCS1_WRONG_PAD -57 #define GNUTLS_E_UNIMPLEMENTED_FEATURE -250 diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index 1aacd4058f..60f2e559d7 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -452,7 +452,6 @@ typedef struct { * client certificates were found. */ x509_cert_callback_func* x509_client_cert_callback; - gnutls_cert peer_cert; int max_handshake_data_buffer_size; /* PUSH & PULL functions. diff --git a/lib/gnutls_kx.c b/lib/gnutls_kx.c index 1b41ad5527..aad059fcb8 100644 --- a/lib/gnutls_kx.c +++ b/lib/gnutls_kx.c @@ -542,10 +542,6 @@ int _gnutls_recv_client_certificate( GNUTLS_STATE state) } /* certificate was required */ if (optional==MANDATORY_PACKET) { -#ifdef DEBUG -# warning FIX THIS ALERT - gnutls_send_alert( state, GNUTLS_FATAL, GNUTLS_BAD_CERTIFICATE); -#endif gnutls_assert(); } return ret; @@ -634,10 +630,6 @@ int _gnutls_recv_client_certificate_verify_message( GNUTLS_STATE state) if (ret==0 && datasize == 0 && state->gnutls_internals.send_cert_req == GNUTLS_CERT_REQUIRE) { /* certificate was required */ -#ifdef DEBUG -# warning FIX THIS ALERT - gnutls_send_alert( state, GNUTLS_FATAL, GNUTLS_BAD_CERTIFICATE); -#endif gnutls_assert(); return GNUTLS_E_NO_CERTIFICATE_FOUND; } diff --git a/lib/gnutls_record.c b/lib/gnutls_record.c index 573fe79677..595b408a97 100644 --- a/lib/gnutls_record.c +++ b/lib/gnutls_record.c @@ -217,7 +217,6 @@ int gnutls_deinit(GNUTLS_STATE state) _gnutls_free(state->gnutls_internals.CompressionMethodPriority.algorithm_priority); _gnutls_free(state->gnutls_internals.db_name); - gnutls_free_cert( state->gnutls_internals.peer_cert); memset( state, 0, sizeof(struct GNUTLS_STATE_INT)); gnutls_free(state); @@ -433,6 +432,7 @@ int ret = GNUTLS_E_UNIMPLEMENTED_FEATURE; ret = gnutls_send_alert( state, GNUTLS_FATAL, GNUTLS_ILLEGAL_PARAMETER); break; case GNUTLS_E_ASN1_PARSING_ERROR: + case GNUTLS_E_NO_CERTIFICATE_FOUND: ret = gnutls_send_alert( state, GNUTLS_FATAL, GNUTLS_BAD_CERTIFICATE); break; case GNUTLS_E_UNKNOWN_CIPHER_SUITE: diff --git a/lib/gnutls_session_pack.c b/lib/gnutls_session_pack.c index 38396d14de..18116d21c2 100644 --- a/lib/gnutls_session_pack.c +++ b/lib/gnutls_session_pack.c @@ -28,11 +28,11 @@ #include <gnutls_num.h> #define PACK_HEADER_SIZE 1 -int _gnutls_pack_x509pki_auth_info(X509PKI_AUTH_INFO info, +int _gnutls_pack_x509pki_auth_info( X509PKI_AUTH_INFO info, gnutls_datum * packed_session); int _gnutls_unpack_x509pki_auth_info(X509PKI_AUTH_INFO info, const gnutls_datum * packed_session); -static int _gnutls_pack_x509pki_auth_info_size(); +static int _gnutls_pack_x509pki_auth_info_size( X509PKI_AUTH_INFO info); /* Since auth_info structures contain malloced data, this function @@ -49,14 +49,19 @@ int _gnutls_session_pack(GNUTLS_STATE state, gnutls_datum * packed_session) return GNUTLS_E_UNIMPLEMENTED_FEATURE; } + switch (gnutls_get_auth_type(state)) { case GNUTLS_SRP:{ SRP_SERVER_AUTH_INFO info = _gnutls_get_auth_info(state); - if (info == NULL || info->username[0] == 0) + + + if (info == NULL && state->gnutls_key->auth_info_size!=0) { + gnutls_assert(); return GNUTLS_E_INVALID_PARAMETERS; + } - pack_size = sizeof(SRP_SERVER_AUTH_INFO_INT); + pack_size = state->gnutls_key->auth_info_size; packed_session->size = PACK_HEADER_SIZE + pack_size + sizeof(uint32); @@ -64,19 +69,22 @@ int _gnutls_session_pack(GNUTLS_STATE state, gnutls_datum * packed_session) WRITEuint32(pack_size, &packed_session-> data[PACK_HEADER_SIZE]); - memcpy(&packed_session-> - data[PACK_HEADER_SIZE + sizeof(uint32)], - info, sizeof(SRP_SERVER_AUTH_INFO_INT)); + + if (state->gnutls_key->auth_info_size > 0) + memcpy(&packed_session-> + data[PACK_HEADER_SIZE + sizeof(uint32)], + info, state->gnutls_key->auth_info_size); } + break; case GNUTLS_ANON:{ ANON_CLIENT_AUTH_INFO info = _gnutls_get_auth_info(state); - if (info == NULL) + if (info == NULL && state->gnutls_key->auth_info_size!=0) return GNUTLS_E_INVALID_PARAMETERS; - pack_size = sizeof(ANON_CLIENT_AUTH_INFO_INT); + pack_size = state->gnutls_key->auth_info_size; packed_session->size = PACK_HEADER_SIZE + pack_size + sizeof(uint32); @@ -84,9 +92,11 @@ int _gnutls_session_pack(GNUTLS_STATE state, gnutls_datum * packed_session) WRITEuint32(pack_size, &packed_session-> data[PACK_HEADER_SIZE]); - memcpy(&packed_session-> - data[PACK_HEADER_SIZE + sizeof(uint32)], - info, sizeof(ANON_CLIENT_AUTH_INFO_INT)); + + if (state->gnutls_key->auth_info_size > 0) + memcpy(&packed_session-> + data[PACK_HEADER_SIZE + sizeof(uint32)], + info, state->gnutls_key->auth_info_size); } break; @@ -119,6 +129,7 @@ int _gnutls_session_pack(GNUTLS_STATE state, gnutls_datum * packed_session) data[packed_session->size - sizeof(SecurityParameters)], &state->security_parameters, sizeof(SecurityParameters)); + return 0; } @@ -134,8 +145,17 @@ int _gnutls_session_size( GNUTLS_STATE state) case GNUTLS_SRP: case GNUTLS_ANON: pack_size += state->gnutls_key->auth_info_size; - case GNUTLS_X509PKI: - pack_size += _gnutls_pack_x509pki_auth_info_size( state); + break; + case GNUTLS_X509PKI: { + X509PKI_AUTH_INFO info = + _gnutls_get_auth_info(state); + + if (info == NULL) + return GNUTLS_E_INVALID_PARAMETERS; + + pack_size += _gnutls_pack_x509pki_auth_info_size( info); + } + break; } /* Auth_info structures copied. Now copy SecurityParameters. @@ -162,14 +182,13 @@ int _gnutls_session_unpack(GNUTLS_STATE state, _gnutls_free_auth_info( state); } - switch (packed_session->data[0]) { + switch ( packed_session->data[0]) { case GNUTLS_SRP:{ pack_size = READuint32(&packed_session-> data[PACK_HEADER_SIZE]); - if (pack_size == 0) break; if (pack_size != sizeof(SRP_SERVER_AUTH_INFO_INT)) { gnutls_assert(); @@ -180,8 +199,10 @@ int _gnutls_session_unpack(GNUTLS_STATE state, gnutls_calloc(1, sizeof (SRP_SERVER_AUTH_INFO_INT)); - if (state->gnutls_key->auth_info == NULL) + if (state->gnutls_key->auth_info == NULL) { + gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; + } state->gnutls_key->auth_info_size = sizeof(SRP_SERVER_AUTH_INFO_INT); @@ -208,8 +229,10 @@ int _gnutls_session_unpack(GNUTLS_STATE state, gnutls_calloc(1, sizeof (ANON_CLIENT_AUTH_INFO_INT)); - if (state->gnutls_key->auth_info == NULL) + if (state->gnutls_key->auth_info == NULL) { + gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; + } state->gnutls_key->auth_info_size = sizeof(ANON_CLIENT_AUTH_INFO_INT); @@ -233,8 +256,10 @@ int _gnutls_session_unpack(GNUTLS_STATE state, state->gnutls_key->auth_info = gnutls_calloc(1, sizeof(X509PKI_AUTH_INFO_INT)); - if (state->gnutls_key->auth_info == NULL) + if (state->gnutls_key->auth_info == NULL) { + gnutls_assert(); return GNUTLS_E_MEMORY_ERROR; + } state->gnutls_key->auth_info_size = sizeof(X509PKI_AUTH_INFO_INT); @@ -248,11 +273,10 @@ int _gnutls_session_unpack(GNUTLS_STATE state, return ret; } - pack_size += ret; - } break; default: + gnutls_assert(); return GNUTLS_E_UNIMPLEMENTED_FEATURE; } @@ -280,7 +304,7 @@ int _gnutls_session_unpack(GNUTLS_STATE state, memcpy( &state->gnutls_internals.resumed_security_parameters, &sp, sizeof(SecurityParameters)); } else { _gnutls_free_auth_info( state); - + gnutls_assert(); return GNUTLS_E_EXPIRED; } @@ -288,57 +312,87 @@ int _gnutls_session_unpack(GNUTLS_STATE state, return 0; } -int _gnutls_pack_x509pki_auth_info(X509PKI_AUTH_INFO info, +int _gnutls_pack_x509pki_auth_info( X509PKI_AUTH_INFO info, gnutls_datum * packed_session) { - uint32 pack_size = sizeof(X509PKI_AUTH_INFO_INT) + info->raw_certificate.size; - packed_session->size = - pack_size + PACK_HEADER_SIZE + sizeof(uint32); + uint32 pos, i; + packed_session->size = _gnutls_pack_x509pki_auth_info_size( info); packed_session->data[0] = GNUTLS_X509PKI; - WRITEuint32(pack_size, &packed_session->data[PACK_HEADER_SIZE]); + WRITEuint32( packed_session->size-PACK_HEADER_SIZE-sizeof(uint32), &packed_session->data[PACK_HEADER_SIZE]); + + memcpy(&packed_session->data[PACK_HEADER_SIZE + sizeof(uint32)], info, sizeof(X509PKI_AUTH_INFO_INT)); - if (info->raw_certificate.size > 0) - memcpy(&packed_session->data[PACK_HEADER_SIZE + sizeof(uint32) + - sizeof(X509PKI_AUTH_INFO_INT)], info->raw_certificate.data, - info->raw_certificate.size); + pos = PACK_HEADER_SIZE + sizeof(uint32) + sizeof(X509PKI_AUTH_INFO_INT); + + for (i=0;i<info->ncerts;i++) { + WRITEuint32( info->raw_certificate_list[i].size, &packed_session->data[pos]); + pos += sizeof(uint32); + + memcpy(&packed_session->data[pos], info->raw_certificate_list[i].data, info->raw_certificate_list[i].size); + pos += info->raw_certificate_list[i].size; + } + return 0; } -static int _gnutls_pack_x509pki_auth_info_size( GNUTLS_STATE state) +static int _gnutls_pack_x509pki_auth_info_size( X509PKI_AUTH_INFO info) { - X509PKI_AUTH_INFO info = - _gnutls_get_auth_info(state); uint32 pack_size = sizeof(X509PKI_AUTH_INFO_INT); + int i; if (info == NULL) return 0; - - return pack_size + PACK_HEADER_SIZE + sizeof(uint32) + info->raw_certificate.size; + + for (i=0;i<info->ncerts;i++) { + pack_size += sizeof(uint32) + info->raw_certificate_list[i].size; + } + + return pack_size + PACK_HEADER_SIZE + sizeof(uint32); } int _gnutls_unpack_x509pki_auth_info(X509PKI_AUTH_INFO info, const gnutls_datum * packed_session) { -int ret; +int ret, i, pos, j; +uint32 size; memcpy(info, &packed_session->data[PACK_HEADER_SIZE + sizeof(uint32)], sizeof(X509PKI_AUTH_INFO_INT)); - if (info->raw_certificate.size > 0) { - ret = gnutls_set_datum( &info->raw_certificate, - &packed_session->data[PACK_HEADER_SIZE + sizeof(uint32) + sizeof(X509PKI_AUTH_INFO_INT)], - info->raw_certificate.size); - - if (ret < 0) { + pos = PACK_HEADER_SIZE + sizeof(uint32) + sizeof(X509PKI_AUTH_INFO_INT); + if (info->ncerts > 0) { + info->raw_certificate_list = gnutls_calloc( 1, info->ncerts * sizeof( gnutls_datum)); + if (info->raw_certificate_list == NULL) { gnutls_assert(); - return ret; + return GNUTLS_E_MEMORY_ERROR; + } + + for (i=0;i<info->ncerts;i++) { + size = READuint32( &packed_session->data[ pos]); + pos += sizeof(uint32); + + ret = gnutls_set_datum( &info->raw_certificate_list[i], &packed_session->data[ pos], size); + pos += size; + + if (ret < 0) { + gnutls_assert(); + goto clear; + } } } return 0; + + clear: + for (j=0;j<i;j++) + gnutls_free_datum( &info->raw_certificate_list[j]); + + gnutls_free( info->raw_certificate_list); + return GNUTLS_E_MEMORY_ERROR; + } diff --git a/lib/gnutls_ui.c b/lib/gnutls_ui.c index fb8fce623e..d1e7f4afa2 100644 --- a/lib/gnutls_ui.c +++ b/lib/gnutls_ui.c @@ -100,38 +100,16 @@ int gnutls_anon_client_get_dh_bits(GNUTLS_STATE state) /* X509PKI */ /** - * gnutls_x509pki_get_peer_certificate_status - This function returns the peer's certificate status + * gnutls_x509pki_get_peer_certificate_list - This function returns the peer's raw (DER encoded) certificate * @state: is a gnutls state + * @list_size: is the length of the certificate list * - * This function will return the peer's certificate status (TRUSTED, EXPIRED etc.). This is the output - * of the certificate verification function. However you must also check the peer's name in order - * to check if the verified certificate belongs to the actual peer. - * Returns GNUTLS_CERT_NONE in case of an error, or if no certificate was sent. - * - **/ -CertificateStatus gnutls_x509pki_get_peer_certificate_status(GNUTLS_STATE - state) -{ - X509PKI_AUTH_INFO info; - - CHECK_AUTH(GNUTLS_X509PKI, GNUTLS_CERT_NONE); - - info = _gnutls_get_auth_info(state); - if (info == NULL) - return GNUTLS_CERT_NONE; - return info->peer_certificate_status; -} - -/** - * gnutls_x509pki_get_peer_certificate - This function returns the peer's raw (DER encoded) certificate - * @state: is a gnutls state - * - * This function will return the peer's raw certificate as sent by the peer. - * This certificate is DER encoded. + * This function will return the peer's raw certificate list as sent by the peer. + * These certificates are DER encoded. * Returns NULL in case of an error, or if no certificate was sent. * **/ -const gnutls_datum *gnutls_x509pki_get_peer_certificate(GNUTLS_STATE state) +const gnutls_datum *gnutls_x509pki_get_peer_certificate_list(GNUTLS_STATE state, int *list_size) { X509PKI_AUTH_INFO info; @@ -140,30 +118,12 @@ const gnutls_datum *gnutls_x509pki_get_peer_certificate(GNUTLS_STATE state) info = _gnutls_get_auth_info(state); if (info == NULL) return NULL; - return &info->raw_certificate; -} - -/** - * gnutls_x509pki_get_peer_certificate_version - This function returns the peer's certificate version - * @state: is a gnutls state - * - * This function will return the peer's certificate version (1, 2, 3). This is obtained by the X509 Certificate - * Version field. If the certificate is invalid then version will be zero. - * Returns a negative value in case of an error. - * - **/ -int gnutls_x509pki_get_peer_certificate_version(GNUTLS_STATE state) -{ - X509PKI_AUTH_INFO info; - - CHECK_AUTH(GNUTLS_X509PKI, GNUTLS_E_INVALID_REQUEST); - info = _gnutls_get_auth_info(state); - if (info == NULL) - return GNUTLS_E_UNKNOWN_ERROR; - return info->peer_certificate_version; + *list_size = info->ncerts; + return info->raw_certificate_list; } + /** * gnutls_x509pki_get_dh_bits - This function returns the number of bits used in a DHE handshake * @state: is a gnutls state @@ -186,71 +146,7 @@ int gnutls_x509pki_get_dh_bits(GNUTLS_STATE state) return info->dh_bits; } -/** - * gnutls_x509pki_get_peer_certificate_activation_time - This function returns the peer's certificate activation time - * @state: is a gnutls state - * - * This function will return the peer's certificate activation time in UNIX time - * (ie seconds since 00:00:00 UTC January 1, 1970). - * Returns a (time_t) -1 in case of an error. - * - **/ -time_t gnutls_x509pki_get_peer_certificate_activation_time(GNUTLS_STATE - state) -{ - X509PKI_AUTH_INFO info; - - CHECK_AUTH(GNUTLS_X509PKI, -1); - info = _gnutls_get_auth_info(state); - if (info == NULL) - return -1; - return info->peer_certificate_activation_time; -} - -/** - * gnutls_x509pki_get_peer_certificate_expiration_time - This function returns the peer's certificate expiration time - * @state: is a gnutls state - * - * This function will return the peer's certificate expiration time in UNIX time - * (ie seconds since 00:00:00 UTC January 1, 1970). - * Returns a (time_t) -1 in case of an error. - * - **/ -time_t gnutls_x509pki_get_peer_certificate_expiration_time(GNUTLS_STATE - state) -{ - X509PKI_AUTH_INFO info; - - CHECK_AUTH(GNUTLS_X509PKI, -1); - - info = _gnutls_get_auth_info(state); - if (info == NULL) - return -1; - return info->peer_certificate_expiration_time; -} - - -/** - * gnutls_x509pki_get_key_usage - This function returns the peer's certificate key usage - * @state: is a gnutls state - * - * This function will return the peer's certificate key usage. This is specified in X509v3 Certificate - * Extensions and is an 8bit string. - * Returns zero in case of an error. - * - **/ -unsigned char gnutls_x509pki_get_key_usage(GNUTLS_STATE state) -{ - X509PKI_AUTH_INFO info; - - CHECK_AUTH(GNUTLS_X509PKI, 0); - - info = _gnutls_get_auth_info(state); - if (info == NULL) - return 0; - return info->keyUsage; -} /** * gnutls_x509pki_get_certificate_request_status - This function returns the certificate request status @@ -274,25 +170,3 @@ int gnutls_x509pki_get_certificate_request_status(GNUTLS_STATE state) } -/** - * gnutls_x509pki_get_subject_dns_name - This function returns the peer's dns name, if any - * @state: is a gnutls state - * - * This function will return the peer's alternative name (the dns part of it). - * This is specified in X509v3 Certificate Extensions. - * GNUTLS will only return the dnsName of the Alternative name, or a null - * string. - * Returns NULL in case of an error. - * - **/ -const char *gnutls_x509pki_get_subject_dns_name(GNUTLS_STATE state) -{ - X509PKI_AUTH_INFO info; - - CHECK_AUTH(GNUTLS_X509PKI, NULL); - - info = _gnutls_get_auth_info(state); - if (info == NULL) - return NULL; - return info->subjectAltDNSName; -} diff --git a/lib/gnutls_ui.h b/lib/gnutls_ui.h index ce7b6f9651..7c268a1be2 100644 --- a/lib/gnutls_ui.h +++ b/lib/gnutls_ui.h @@ -61,14 +61,14 @@ int gnutls_x509pki_set_cert_request( GNUTLS_STATE, CertificateRequest); int gnutls_x509pki_get_certificate_request_status( GNUTLS_STATE); int gnutls_x509pki_get_peer_dn( GNUTLS_STATE, gnutls_DN*); -const gnutls_datum* gnutls_x509pki_get_peer_certificate( GNUTLS_STATE); +const gnutls_datum* gnutls_x509pki_get_peer_certificate_list( GNUTLS_STATE, int* list_size); int gnutls_x509pki_get_issuer_dn( GNUTLS_STATE, gnutls_DN *); CertificateStatus gnutls_x509pki_get_peer_certificate_status( GNUTLS_STATE); int gnutls_x509pki_get_peer_certificate_version( GNUTLS_STATE); time_t gnutls_x509pki_get_peer_certificate_activation_time( GNUTLS_STATE); time_t gnutls_x509pki_get_peer_certificate_expiration_time( GNUTLS_STATE); unsigned char gnutls_x509pki_get_key_usage( GNUTLS_STATE); -const char* gnutls_x509pki_get_subject_dns_name( GNUTLS_STATE); +int gnutls_x509pki_get_subject_dns_name( GNUTLS_STATE, char*, int*); int gnutls_x509pki_get_dh_bits( GNUTLS_STATE); #define gnutls_x509pki_server_get_dh_bits gnutls_x509pki_get_dh_bits diff --git a/lib/x509_extensions.c b/lib/x509_extensions.c index 702410e4b8..0e6f7c5bb6 100644 --- a/lib/x509_extensions.c +++ b/lib/x509_extensions.c @@ -25,88 +25,33 @@ #include <gnutls_cert.h> #include <gnutls_errors.h> #include <gnutls_global.h> +#include "debug.h" -/* Here we only read subjectAltDNSName, in case of - * dnsName. Otherwise we read nothing. - */ -static int _extract_subjectAltDNSName( char* subjectAltDNSName, opaque* extnValue, int extnValueLen) { -node_asn* ext; -char counter[MAX_INT_DIGITS]; -char name[1024]; -char str[1024]; -int len, k, result; - - subjectAltDNSName[0] = 0; - - if (asn1_create_structure - ( _gnutls_get_pkix(), "PKIX1Implicit88.GeneralNames", &ext, - "san") != ASN_OK) { - gnutls_assert(); - return GNUTLS_E_ASN1_PARSING_ERROR; - } - - result = asn1_get_der ( ext, extnValue, extnValueLen); - - if (result != ASN_OK) { - gnutls_assert(); - asn1_delete_structure(ext); - return GNUTLS_E_ASN1_PARSING_ERROR; - } - - k = 1; - for (;;) { - strcpy(name, "san.?"); - _gnutls_int2str(k, counter); - strcat(name, counter); - - len = sizeof(str) - 1; - result = asn1_read_value(ext, name, str, &len); - if (result == ASN_ELEMENT_NOT_FOUND) break; - - if (strcmp( str, "dNSName") == 0) { - strcat( name, "dNSName"); - len = sizeof( str) -1; - result = asn1_read_value(ext, name, str, &len); - - if (result != ASN_OK) { - gnutls_assert(); - asn1_delete_structure(ext); - return GNUTLS_E_ASN1_PARSING_ERROR; - } - - strncpy( subjectAltDNSName, str, GMIN( len, X509_CN_SIZE-1)); - subjectAltDNSName[X509_CN_SIZE-1] = 0; - - break; - } - k++; - } - - asn1_delete_structure(ext); - return 0; -} /* Here we only extract the KeyUsage field */ -static int _extract_keyUsage( char* keyUsage, opaque* extnValue, int extnValueLen) { -node_asn* ext; -char str[128]; -int len, result; +static int _extract_keyUsage(char *keyUsage, opaque * extnValue, + int extnValueLen) +{ + node_asn *ext; + char str[10]; + int len, result; + keyUsage[0] = 0; if (asn1_create_structure - ( _gnutls_get_pkix(), "PKIX1Implicit88.KeyUsage", &ext, - "ku") != ASN_OK) { + (_gnutls_get_pkix(), "PKIX1Implicit88.KeyUsage", &ext, + "ku") != ASN_OK) { gnutls_assert(); return GNUTLS_E_ASN1_PARSING_ERROR; } - result = asn1_get_der ( ext, extnValue, extnValueLen); + result = asn1_get_der(ext, extnValue, extnValueLen); if (result != ASN_OK) { gnutls_assert(); asn1_delete_structure(ext); - return GNUTLS_E_ASN1_PARSING_ERROR; + return 0; } len = sizeof(str) - 1; @@ -114,7 +59,7 @@ int len, result; if (result != ASN_OK) { gnutls_assert(); asn1_delete_structure(ext); - return GNUTLS_E_ASN1_PARSING_ERROR; + return 0; } keyUsage[0] = str[0]; @@ -124,29 +69,28 @@ int len, result; return 0; } -static int _extract_basicConstraints( int* CA, opaque* extnValue, int extnValueLen) { -node_asn* ext; -char str[128]; -int len, result; +static int _extract_basicConstraints(int *CA, opaque * extnValue, + int extnValueLen) +{ + node_asn *ext; + char str[128]; + int len, result; *CA = 0; - + if (asn1_create_structure - ( _gnutls_get_pkix(), "PKIX1Implicit88.BasicConstraints", &ext, - "bc") != ASN_OK) { + (_gnutls_get_pkix(), "PKIX1Implicit88.BasicConstraints", &ext, + "bc") != ASN_OK) { gnutls_assert(); return GNUTLS_E_ASN1_PARSING_ERROR; } - result = asn1_get_der ( ext, extnValue, extnValueLen); + result = asn1_get_der(ext, extnValue, extnValueLen); if (result != ASN_OK) { gnutls_assert(); asn1_delete_structure(ext); - return 0; /* GNUTLS_E_ASN1_PARSING_ERROR may be better - * but we want to continue even if the - * certificate is badly formated. - */ + return 0; } len = sizeof(str) - 1; @@ -154,47 +98,50 @@ int len, result; if (result != ASN_OK) { gnutls_assert(); asn1_delete_structure(ext); - return 0; /* see above. - */ + return 0; } asn1_delete_structure(ext); - if ( strcmp(str, "TRUE")==0) *CA = 1; - else *CA = 0; + if (strcmp(str, "TRUE") == 0) + *CA = 1; + else + *CA = 0; return 0; } -static int _parse_extension( gnutls_cert* cert, char* extnID, char* critical, char* extnValue, int extnValueLen) { +static int _parse_extension(gnutls_cert * cert, char *extnID, + char *critical, char *extnValue, + int extnValueLen) +{ - if (strcmp( extnID, "2 5 29 14")==0) { /* subject Key ID */ + if (strcmp(extnID, "2 5 29 14") == 0) { /* subject Key ID */ /* we don't use it */ return 0; } - if (strcmp( extnID, "2 5 29 15")==0) { /* Key Usage */ - return _extract_keyUsage( &cert->keyUsage, extnValue, extnValueLen); + if (strcmp(extnID, "2 5 29 15") == 0) { /* Key Usage */ +fprintf(stderr, "key USAGE FOUND\n"); + return _extract_keyUsage(&cert->keyUsage, extnValue, extnValueLen); } - if (strcmp( extnID, "2 5 29 19")==0) { /* Basic Constraints */ + if (strcmp(extnID, "2 5 29 19") == 0) { /* Basic Constraints */ /* actually checks if a certificate belongs to * a Certificate Authority. */ - return _extract_basicConstraints( &cert->CA, extnValue, extnValueLen); - } - - if (strcmp( extnID, "2 5 29 17")==0) { /* subjectAltDNSName */ - return _extract_subjectAltDNSName( cert->subjectAltDNSName, extnValue, extnValueLen); + return _extract_basicConstraints(&cert->CA, extnValue, + extnValueLen); } #ifdef DEBUG - _gnutls_log("CERT[%s]: Unsupported Extension: %s, %s\n", GET_CN(cert->raw), extnID, critical); + _gnutls_log("CERT[%s]: Unsupported Extension: %s, %s\n", + GET_CN(cert->raw), extnID, critical); #endif - - if (strcmp( critical, "TRUE")==0) { + + if (strcmp(critical, "TRUE") == 0) { gnutls_assert(); return GNUTLS_E_X509_UNSUPPORTED_CRITICAL_EXTENSION; } @@ -205,7 +152,7 @@ static int _parse_extension( gnutls_cert* cert, char* extnID, char* critical, ch /* This function will attempt to parse Extensions in * an X509v3 certificate */ -int _gnutls_get_ext_type( node_asn *rasn, char *root, gnutls_cert *cert) +int _gnutls_get_ext_type(node_asn * rasn, char *root, gnutls_cert * cert) { int k, result, len; char name[128], name2[128], counter[MAX_INT_DIGITS]; @@ -217,19 +164,20 @@ int _gnutls_get_ext_type( node_asn *rasn, char *root, gnutls_cert *cert) k = 0; do { k++; - + strcpy(name, root); strcat(name, ".?"); _gnutls_int2str(k, counter); strcat(name, counter); len = sizeof(str) - 1; - result = asn1_read_value( rasn, name, str, &len); - + result = asn1_read_value(rasn, name, str, &len); + /* move to next */ - if (result==ASN_ELEMENT_NOT_FOUND) break; + if (result == ASN_ELEMENT_NOT_FOUND) + break; do { @@ -237,60 +185,207 @@ int _gnutls_get_ext_type( node_asn *rasn, char *root, gnutls_cert *cert) strcat(name2, ".extnID"); len = sizeof(extnID) - 1; - result = asn1_read_value( rasn, name2, extnID, &len); + result = + asn1_read_value(rasn, name2, extnID, &len); - if (result==ASN_ELEMENT_NOT_FOUND) break; - else - if (result != ASN_OK) { - gnutls_assert(); - return GNUTLS_E_ASN1_PARSING_ERROR; - } + if (result == ASN_ELEMENT_NOT_FOUND) + break; + else if (result != ASN_OK) { + gnutls_assert(); + return GNUTLS_E_ASN1_PARSING_ERROR; + } strcpy(name2, name); strcat(name2, ".critical"); - + len = sizeof(critical) - 1; - result = asn1_read_value( rasn, name2, critical, &len); + result = + asn1_read_value(rasn, name2, critical, &len); - if (result==ASN_ELEMENT_NOT_FOUND) break; - else + if (result == ASN_ELEMENT_NOT_FOUND) + break; + else if (result != ASN_OK) { + gnutls_assert(); + return GNUTLS_E_ASN1_PARSING_ERROR; + } + + strcpy(name2, name); + strcat(name2, ".extnValue"); + + len = sizeof(extnValue) - 1; + result = + asn1_read_value(rasn, name2, extnValue, &len); + + if (result == ASN_ELEMENT_NOT_FOUND) + break; + else { + if (result == ASN_MEM_ERROR + && strcmp(critical, "FALSE") == 0) { +#ifdef DEBUG + _gnutls_log + ("Cannot parse extension: %s. Too small buffer.", + extnID); +#endif + continue; + } if (result != ASN_OK) { gnutls_assert(); return GNUTLS_E_ASN1_PARSING_ERROR; } - + } + + /* Handle Extension */ + if ((result = + _parse_extension(cert, extnID, critical, + extnValue, len)) < 0) { + gnutls_assert(); + return result; + } + + + } while (0); + } while (1); + + if (result == ASN_ELEMENT_NOT_FOUND) + return 0; + else + return GNUTLS_E_ASN1_PARSING_ERROR; +} + +/* This function will attempt to return the requested extension found in + * the given X509v3 certificate. The return value is allocated and stored into + * ret. + */ +int _gnutls_get_extension( const gnutls_datum * cert, const char* extension_id, gnutls_datum* ret) +{ + int k, result, len; + char name[128], name2[128], counter[MAX_INT_DIGITS]; + char str[1024]; + char critical[10]; + char extnID[128]; + char extnValue[256]; + node_asn* rasn; + + ret->data = NULL; + ret->size = 0; + + if (asn1_create_structure + (_gnutls_get_pkix(), "PKIX1Implicit88.Certificate", &rasn, + "certificate2") + != ASN_OK) { + gnutls_assert(); + return GNUTLS_E_ASN1_ERROR; + } + + result = + asn1_get_der(rasn, cert->data, cert->size); + if (result != ASN_OK) { + /* couldn't decode DER */ +#ifdef DEBUG + _gnutls_log("Decoding error %d\n", result); +#endif + gnutls_assert(); + asn1_delete_structure(rasn); + return GNUTLS_E_ASN1_PARSING_ERROR; + } + + k = 0; + do { + k++; + + strcpy(name, "certificate2"); + strcat(name, ".?"); + _gnutls_int2str(k, counter); + strcat(name, counter); + + len = sizeof(str) - 1; + result = asn1_read_value(rasn, name, str, &len); + + /* move to next + */ + + if (result == ASN_ELEMENT_NOT_FOUND) + break; + + do { + + strcpy(name2, name); + strcat(name2, ".extnID"); + + len = sizeof(extnID) - 1; + result = + asn1_read_value(rasn, name2, extnID, &len); + + if (result == ASN_ELEMENT_NOT_FOUND) + break; + else if (result != ASN_OK) { + gnutls_assert(); + return GNUTLS_E_ASN1_PARSING_ERROR; + } + + strcpy(name2, name); + strcat(name2, ".critical"); + + len = sizeof(critical) - 1; + result = + asn1_read_value(rasn, name2, critical, &len); + + if (result == ASN_ELEMENT_NOT_FOUND) + break; + else if (result != ASN_OK) { + gnutls_assert(); + asn1_delete_structure(rasn); + return GNUTLS_E_ASN1_PARSING_ERROR; + } + strcpy(name2, name); strcat(name2, ".extnValue"); - len = sizeof( extnValue) - 1; - result = asn1_read_value( rasn, name2, extnValue, &len); + len = sizeof(extnValue) - 1; + result = + asn1_read_value(rasn, name2, extnValue, &len); - if (result==ASN_ELEMENT_NOT_FOUND) break; + if (result == ASN_ELEMENT_NOT_FOUND) + break; else { - if (result==ASN_MEM_ERROR && strcmp(critical, "FALSE")==0) { + if (result == ASN_MEM_ERROR + && strcmp(critical, "FALSE") == 0) { #ifdef DEBUG - _gnutls_log("Cannot parse extension: %s. Too small buffer.", extnID); + _gnutls_log + ("Cannot parse extension: %s. Too small buffer.", + extnID); #endif continue; } if (result != ASN_OK) { gnutls_assert(); + asn1_delete_structure(rasn); return GNUTLS_E_ASN1_PARSING_ERROR; } } - + /* Handle Extension */ - if ( (result=_parse_extension( cert, extnID, critical, extnValue, len)) < 0) { - gnutls_assert(); - return result; + if ( strcmp(extnID, extension_id)==0) { /* extension was found */ + asn1_delete_structure(rasn); + ret->data = gnutls_malloc( len); + if (ret->data==NULL) + return GNUTLS_E_MEMORY_ERROR; + + ret->size = len; + memcpy( ret->data, extnValue, len); + + return 0; } - - + + } while (0); } while (1); - if (result==ASN_ELEMENT_NOT_FOUND) - return 0; - else + asn1_delete_structure(rasn); + + + if (result == ASN_ELEMENT_NOT_FOUND) + return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE; + else return GNUTLS_E_ASN1_PARSING_ERROR; } diff --git a/lib/x509_extensions.h b/lib/x509_extensions.h index 8935071025..1d4d1c82d0 100644 --- a/lib/x509_extensions.h +++ b/lib/x509_extensions.h @@ -1 +1,2 @@ int _gnutls_get_ext_type( node_asn *rasn, char *root, gnutls_cert *cert); +int _gnutls_get_extension( const gnutls_datum * cert, const char* extension_id, gnutls_datum* ret); diff --git a/src/Makefile.am b/src/Makefile.am index cbb75e3988..2daea7c769 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,4 +1,4 @@ -EXTRA_DIST = port.h prime.gaa crypt.gaa crypt-gaa.h README.crypt prime-gaa.h \ +EXTRA_DIST = common.h prime.gaa crypt.gaa crypt-gaa.h README.crypt prime-gaa.h \ README SUBDIRS = srp x509 @@ -31,6 +31,7 @@ #include <sys/time.h> #include <signal.h> #include <netdb.h> +#include <common.h> #ifndef SHUT_WR # define SHUT_WR 1 @@ -52,22 +53,13 @@ #define CLIKEYFILE "x509/clikey.pem" #define CLICERTFILE "x509/clicert.pem" -#define PRINTX(x,y) if (y[0]!=0) printf(" - %s %s\n", x, y) -#define PRINT_DN(X) PRINTX( "CN:", X.common_name); \ - PRINTX( "OU:", X.organizational_unit_name); \ - PRINTX( "O:", X.organization); \ - PRINTX( "L:", X.locality_name); \ - PRINTX( "S:", X.state_or_province_name); \ - PRINTX( "C:", X.country); \ - PRINTX( "E:", X.email); \ - PRINTX( "SAN:", gnutls_x509pki_client_get_subject_dns_name(state)) - static int print_info( GNUTLS_STATE state) { const char *tmp; CredType cred; gnutls_DN dn; CertificateStatus status; - +char dnsname[512]; +int dnsname_size; tmp = gnutls_kx_get_name(gnutls_get_current_kx( state)); printf("- Key Exchange: %s\n", tmp); diff --git a/src/common.h b/src/common.h new file mode 100644 index 0000000000..56f77d4bc5 --- /dev/null +++ b/src/common.h @@ -0,0 +1,14 @@ +#define PORT 5556 +#define SERVER "127.0.0.1" + +#define PRINTX(x,y) if (y[0]!=0) printf(" - %s %s\n", x, y) +#define PRINT_DN(X) PRINTX( "CN:", X.common_name); \ + PRINTX( "OU:", X.organizational_unit_name); \ + PRINTX( "O:", X.organization); \ + PRINTX( "L:", X.locality_name); \ + PRINTX( "S:", X.state_or_province_name); \ + PRINTX( "C:", X.country); \ + PRINTX( "E:", X.email); \ + dnsname_size = sizeof(dnsname); \ + gnutls_x509pki_client_get_subject_dns_name(state, dnsname, &dnsname_size); \ + PRINTX( "SAN:", dnsname) diff --git a/src/port.h b/src/port.h deleted file mode 100644 index 696b48cb7d..0000000000 --- a/src/port.h +++ /dev/null @@ -1,2 +0,0 @@ -#define PORT 5556 -#define SERVER "127.0.0.1" diff --git a/src/serv.c b/src/serv.c index 8bf777f159..763da05504 100644 --- a/src/serv.c +++ b/src/serv.c @@ -28,7 +28,7 @@ #include <string.h> #include <unistd.h> #include "../lib/gnutls.h" -#include <port.h> +#include <common.h> #include <signal.h> #define KEYFILE "x509/key.pem" @@ -100,15 +100,6 @@ GNUTLS_STATE initialize_state() return state; } -#define PRINTX(x,y) if (y[0]!=0) printf(" - %s %s\n", x, y) -#define PRINT_DN(X) PRINTX( "CN:", X.common_name); \ - PRINTX( "OU:", X.organizational_unit_name); \ - PRINTX( "O:", X.organization); \ - PRINTX( "L:", X.locality_name); \ - PRINTX( "S:", X.state_or_province_name); \ - PRINTX( "C:", X.country); \ - PRINTX( "E:", X.email); \ - PRINTX( "SAN:", gnutls_x509pki_client_get_subject_dns_name(state)) void print_info(GNUTLS_STATE state) { @@ -118,6 +109,8 @@ void print_info(GNUTLS_STATE state) gnutls_DN dn; CredType cred; CertificateStatus status; + char dnsname[512]; + int dnsname_size; /* print session_id specific data */ gnutls_get_current_session_id( state, sesid, &sesid_size); |