diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2001-11-29 15:29:54 +0000 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2001-11-29 15:29:54 +0000 |
commit | c89ee7ef6caff8f6929702db1859c22c1ec4adc3 (patch) | |
tree | d54067c4bc4ef3e6b8c5e9d1ba72f55ed225ab74 /lib | |
parent | 47580d3bd319cbacab763a9bb0f293e9a79ebed6 (diff) | |
download | gnutls-c89ee7ef6caff8f6929702db1859c22c1ec4adc3.tar.gz |
introduced gnutls_x509pki_get_certificate(). This function returns the
peer's certificate DER encoded. This certificate is also stored in the
resume db.
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Makefile.am | 4 | ||||
-rw-r--r-- | lib/auth_anon.c | 13 | ||||
-rw-r--r-- | lib/auth_dhe_rsa.c | 9 | ||||
-rw-r--r-- | lib/auth_rsa.c | 1 | ||||
-rw-r--r-- | lib/auth_srp.c | 8 | ||||
-rw-r--r-- | lib/auth_x509.c | 30 | ||||
-rw-r--r-- | lib/auth_x509.h | 9 | ||||
-rw-r--r-- | lib/gnutls_algorithms.c | 2 | ||||
-rw-r--r-- | lib/gnutls_auth.c | 45 | ||||
-rw-r--r-- | lib/gnutls_db.c | 22 | ||||
-rw-r--r-- | lib/gnutls_int.h | 11 | ||||
-rw-r--r-- | lib/gnutls_record.c | 31 | ||||
-rw-r--r-- | lib/gnutls_session.c | 57 | ||||
-rw-r--r-- | lib/gnutls_session_pack.c | 344 | ||||
-rw-r--r-- | lib/gnutls_session_pack.h | 3 | ||||
-rw-r--r-- | lib/gnutls_ui.c | 21 | ||||
-rw-r--r-- | lib/gnutls_ui.h | 3 |
17 files changed, 529 insertions, 84 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am index f65d5c3cd7..42ace9e549 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -17,7 +17,7 @@ EXTRA_DIST = debug.h gnutls_compress.h defines.h pkcs1.asn pkix.asn \ ext_dnsname.h gnutls_pk.h gnutls_record.h gnutls_cert.h \ gnutls_privkey.h gnutls_constate.h gnutls_global.h x509_verify.h \ gnutls_sig.h gnutls_mem.h x509_extensions.h gnutls_ui.h \ - gnutls-api.tex io_debug.h ext_max_record.h + gnutls-api.tex io_debug.h ext_max_record.h gnutls_session_pack.h lib_LTLIBRARIES = libgnutls.la @@ -30,7 +30,7 @@ COBJECTS = gnutls_record.c gnutls_compress.c debug.c \ auth_anon.c auth_dhe_dss.c gnutls_extensions.c ext_srp.c gnutls_auth.c \ crypt_bcrypt.c crypt.c gnutls_random.c crypt_srpsha1.c gnutls_srp.c \ auth_srp.c auth_srp_passwd.c gnutls_v2_compat.c auth_srp_sb64.c \ - gnutls_datum.c auth_rsa.c \ + gnutls_datum.c auth_rsa.c gnutls_session_pack.c \ gnutls_gcry.c ext_dnsname.c gnutls_pk.c gnutls_cert.c x509_verify.c\ gnutls_global.c gnutls_privkey.c gnutls_constate.c gnutls_anon_cred.c \ x509_sig_check.c pkix_asn1_tab.c pkcs1_asn1_tab.c gnutls_mem.c \ diff --git a/lib/auth_anon.c b/lib/auth_anon.c index 17284e6a7d..ba2341e881 100644 --- a/lib/auth_anon.c +++ b/lib/auth_anon.c @@ -87,11 +87,18 @@ int gen_anon_server_kx( GNUTLS_STATE state, opaque** data) { return GNUTLS_E_MEMORY_ERROR; } - state->gnutls_key->auth_info = gnutls_malloc(sizeof(ANON_SERVER_AUTH_INFO)); - if (state->gnutls_key->auth_info==NULL) return GNUTLS_E_MEMORY_ERROR; + if ( state->gnutls_key->auth_info == NULL) { + state->gnutls_key->auth_info = gnutls_malloc(sizeof(ANON_SERVER_AUTH_INFO)); + if (state->gnutls_key->auth_info==NULL) return GNUTLS_E_MEMORY_ERROR; + state->gnutls_key->auth_info_type = GNUTLS_ANON; + state->gnutls_key->auth_info_size = sizeof(ANON_SERVER_AUTH_INFO_INT); + } else + if (gnutls_get_auth_type( state) != state->gnutls_key->auth_info_type) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } ((ANON_SERVER_AUTH_INFO)state->gnutls_key->auth_info)->dh_bits = gcry_mpi_get_nbits(p); - state->gnutls_key->auth_info_size = sizeof(ANON_SERVER_AUTH_INFO_INT); X = gnutls_calc_dh_secret(&x, g, p); if (X==NULL || x==NULL) { diff --git a/lib/auth_dhe_rsa.c b/lib/auth_dhe_rsa.c index bec7454fcc..d6f7b8291c 100644 --- a/lib/auth_dhe_rsa.c +++ b/lib/auth_dhe_rsa.c @@ -102,7 +102,14 @@ static int gen_dhe_rsa_server_kx(GNUTLS_STATE state, opaque ** data) info = state->gnutls_key->auth_info; info->dh_bits = gcry_mpi_get_nbits(p); info->peer_certificate_status = GNUTLS_CERT_NONE; - } + 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; + } + info = state->gnutls_key->auth_info; X = gnutls_calc_dh_secret(&x, g, p); diff --git a/lib/auth_rsa.c b/lib/auth_rsa.c index ee4c838750..1073fe7c9b 100644 --- a/lib/auth_rsa.c +++ b/lib/auth_rsa.c @@ -70,6 +70,7 @@ MOD_AUTH_STRUCT rsa_auth_struct = #define RANDOMIZE_KEY(x, galloc) x.size=TLS_MASTER_SIZE; x.data=galloc(x.size); \ if (x.data==NULL) return GNUTLS_E_MEMORY_ERROR; \ if (_gnutls_get_random( x.data, x.size, GNUTLS_WEAK_RANDOM) < 0) { \ + gnutls_assert(); \ return GNUTLS_E_MEMORY_ERROR; \ } diff --git a/lib/auth_srp.c b/lib/auth_srp.c index 7d36b4344d..e017f53835 100644 --- a/lib/auth_srp.c +++ b/lib/auth_srp.c @@ -76,8 +76,14 @@ int gen_srp_server_hello(GNUTLS_STATE state, opaque ** data) GNUTLS_SRP_PWD_ENTRY *pwd_entry; int err; - if ( state->gnutls_key->auth_info == NULL) + if ( state->gnutls_key->auth_info == NULL) { state->gnutls_key->auth_info = gnutls_calloc(1, sizeof(SRP_SERVER_AUTH_INFO_INT)); + state->gnutls_key->auth_info_type = GNUTLS_SRP; + } else + if (gnutls_get_auth_type( state) != state->gnutls_key->auth_info_type) { + gnutls_assert(); + return GNUTLS_E_INVALID_REQUEST; + } if (state->gnutls_key->auth_info == NULL) { gnutls_assert(); diff --git a/lib/auth_x509.c b/lib/auth_x509.c index 41b739531a..be6b67377a 100644 --- a/lib/auth_x509.c +++ b/lib/auth_x509.c @@ -40,9 +40,11 @@ /* Copies data from a internal certificate struct (gnutls_cert) to * exported certificate struct (X509PKI_AUTH_INFO) */ -void _gnutls_copy_x509_client_auth_info( X509PKI_AUTH_INFO info, gnutls_cert* cert, CertificateStatus verify) { +int _gnutls_copy_x509_client_auth_info( X509PKI_AUTH_INFO info, gnutls_cert* cert, CertificateStatus verify) { /* Copy peer's information to AUTH_INFO */ +int ret; + memcpy( &info->peer_dn, &cert->cert_info, sizeof(gnutls_DN)); memcpy( &info->issuer_dn, &cert->issuer_info, sizeof(gnutls_DN)); @@ -59,7 +61,15 @@ void _gnutls_copy_x509_client_auth_info( X509PKI_AUTH_INFO info, gnutls_cert* ce info->peer_certificate_expiration_time = cert->expiration_time; info->peer_certificate_activation_time = cert->activation_time; - return; + 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; + } + } + + return 0; } typedef struct { @@ -536,6 +546,8 @@ int _gnutls_proc_x509_server_certificate(GNUTLS_STATE state, opaque * data, int gnutls_assert(); return GNUTLS_E_INSUFICIENT_CRED; } + + 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) { @@ -546,7 +558,14 @@ int _gnutls_proc_x509_server_certificate(GNUTLS_STATE state, opaque * data, int info = state->gnutls_key->auth_info; info->peer_certificate_status = GNUTLS_CERT_NONE; - } + + 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; + } + info = state->gnutls_key->auth_info; DECR_LEN(dsize, 3); @@ -647,7 +666,10 @@ 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; - _gnutls_copy_x509_client_auth_info(info, &peer_certificate_list[0], verify); + if ( (ret = _gnutls_copy_x509_client_auth_info(info, &peer_certificate_list[0], verify)) < 0) { + gnutls_assert(); + return ret; + } if ( (ret=_gnutls_check_x509_key_usage( &peer_certificate_list[0], gnutls_get_current_kx( state))) < 0) { gnutls_assert(); diff --git a/lib/auth_x509.h b/lib/auth_x509.h index e4e61a076b..9d7d8b0faa 100644 --- a/lib/auth_x509.h +++ b/lib/auth_x509.h @@ -46,13 +46,18 @@ typedef struct X509PKI_AUTH_INFO_INT { time_t peer_certificate_expiration_time; char subjectAltDNSName[X509_CN_SIZE]; unsigned char keyUsage; - int certificate_requested; + 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 + * peer. + */ } *X509PKI_AUTH_INFO; typedef struct X509PKI_AUTH_INFO_INT X509PKI_AUTH_INFO_INT; -void _gnutls_copy_x509_client_auth_info( X509PKI_AUTH_INFO info, gnutls_cert* cert, CertificateStatus verify); +int _gnutls_copy_x509_client_auth_info( X509PKI_AUTH_INFO info, gnutls_cert* cert, CertificateStatus verify); /* AUTH X509 functions */ int _gnutls_gen_x509_server_certificate(GNUTLS_STATE, opaque **); diff --git a/lib/gnutls_algorithms.c b/lib/gnutls_algorithms.c index 40d78dec0a..e5072e12fd 100644 --- a/lib/gnutls_algorithms.c +++ b/lib/gnutls_algorithms.c @@ -675,7 +675,7 @@ const char *gnutls_kx_get_name(KXAlgorithm algorithm) char *ret = NULL; /* avoid prefix */ - GNUTLS_KX_ALG_LOOP(ret = p->name + sizeof("GNUTLS_") - 1); + GNUTLS_KX_ALG_LOOP(ret = p->name + sizeof("GNUTLS_KX_") - 1); return ret; } diff --git a/lib/gnutls_auth.c b/lib/gnutls_auth.c index ce9ca1cc27..8af9a04696 100644 --- a/lib/gnutls_auth.c +++ b/lib/gnutls_auth.c @@ -23,6 +23,7 @@ #include "gnutls_auth.h" #include "gnutls_auth_int.h" #include "gnutls_algorithms.h" +#include "auth_x509.h" #include "auth_anon.h" /* The functions here are used in order for authentication algorithms @@ -135,8 +136,10 @@ int gnutls_set_cred( GNUTLS_STATE state, CredType type, void* cred) { **/ CredType gnutls_get_auth_type( GNUTLS_STATE state) { + return _gnutls_map_kx_get_cred( - state->security_parameters.kx_algorithm); + _gnutls_cipher_suite_get_kx_algo + (state->security_parameters.current_cipher_suite)); } /* @@ -182,3 +185,43 @@ void* _gnutls_get_auth_info( GNUTLS_STATE state) { return state->gnutls_key->auth_info; } +/*- + * _gnutls_free_auth_info - Frees the auth info structure + * @state: is a &GNUTLS_STATE structure. + * + * this function frees the auth info structure and sets it to + * null. It must be called since some structures contain malloced + * elements. + -*/ +void _gnutls_free_auth_info( GNUTLS_STATE state) { + if (state==NULL || state->gnutls_key==NULL) { + gnutls_assert(); + return; + } + + switch ( state->gnutls_key->auth_info_type) { + case GNUTLS_SRP: + case GNUTLS_ANON: + + break; + case GNUTLS_X509PKI: { + X509PKI_AUTH_INFO info = + _gnutls_get_auth_info(state); + + if (info==NULL) break; + gnutls_free( info->raw_certificate.data); + + } + break; + default: + return; + + } + + gnutls_free( state->gnutls_key->auth_info); + state->gnutls_key->auth_info = NULL; + state->gnutls_key->auth_info_size = 0; + state->gnutls_key->auth_info_type = 0; + +} + diff --git a/lib/gnutls_db.c b/lib/gnutls_db.c index 88ebc989e9..7e68afd101 100644 --- a/lib/gnutls_db.c +++ b/lib/gnutls_db.c @@ -26,6 +26,7 @@ #include "gnutls_session.h" #include <gnutls_db.h> #include "debug.h" +#include <gnutls_session_pack.h> #define GNUTLS_DBNAME state->gnutls_internals.db_name @@ -242,13 +243,13 @@ gnutls_datum _key; } /* The format of storing data is: - * SECURITY_PARAMETERS + AUTH_INFO_SIZE + AUTH_INFO + * (forget it). Check gnutls_session_pack.c */ int _gnutls_server_register_current_session( GNUTLS_STATE state) { gnutls_datum key = { state->security_parameters.session_id, state->security_parameters.session_id_size }; gnutls_datum content; -int ret = 0, pos; +int ret = 0; if (state->gnutls_internals.resumable==RESUME_FALSE) return GNUTLS_E_INVALID_SESSION; @@ -257,20 +258,17 @@ int ret = 0, pos; return GNUTLS_E_INVALID_SESSION; /* allocate space for data */ - content.size = sizeof(SecurityParameters) + state->gnutls_key->auth_info_size - + sizeof(state->gnutls_key->auth_info_size); + content.size = _gnutls_session_size( state); content.data = gnutls_malloc( content.size); if (content.data==NULL) return GNUTLS_E_MEMORY_ERROR; /* copy data */ - pos = 0; - memcpy( &content.data[0], (void*)&state->security_parameters, sizeof(SecurityParameters)); - pos+=sizeof(SecurityParameters); - - memcpy( &content.data[pos], &state->gnutls_key->auth_info_size, sizeof(state->gnutls_key->auth_info_size)); - pos+=sizeof(state->gnutls_key->auth_info_size); - - memcpy( &content.data[pos], state->gnutls_key->auth_info, state->gnutls_key->auth_info_size); + ret = _gnutls_session_pack( state, &content); + if (ret < 0) { + gnutls_free( content.data); + gnutls_assert(); + return ret; + } ret = _gnutls_store_session( state, key, content); diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index 3264bf1599..caf6c5bbba 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -31,9 +31,9 @@ #define WRITE_DEBUG #define READ_DEBUG #define HANDSHAKE_DEBUG // Prints some information on handshake -#define RECORD_DEBUG +#define RECORD_DEBUG*/ #define DEBUG -*/ + /* It might be a good idea to replace int with void* * here. @@ -201,10 +201,12 @@ struct GNUTLS_KEY_INT { /* this is used to hold the peers authentication data */ - /* AUTH_INFO structures MUST NOT contain malloced - * elements. + /* AUTH_INFO structures MAY contain malloced + * elements. Check gnutls_session_pack.c, and gnutls_auth.c. + * Rememember that this should be calloced! */ void* auth_info; + CredType auth_info_type; int auth_info_size; /* needed in order to store to db for restoring */ uint8 crypt_algo; @@ -494,6 +496,7 @@ svoid *gnutls_PRF( opaque * secret, int secret_size, uint8 * label, int total_bytes); void _gnutls_set_current_version(GNUTLS_STATE state, GNUTLS_Version version); GNUTLS_Version gnutls_get_current_version(GNUTLS_STATE state); +void _gnutls_free_auth_info( GNUTLS_STATE state); /* These two macros return the advertized TLS version of * the peer. diff --git a/lib/gnutls_record.c b/lib/gnutls_record.c index 3f26919ac5..1875e5d322 100644 --- a/lib/gnutls_record.c +++ b/lib/gnutls_record.c @@ -157,7 +157,7 @@ int gnutls_deinit(GNUTLS_STATE state) } /* remove auth info firstly */ - _gnutls_free(state->gnutls_key->auth_info); + _gnutls_free_auth_info(state ); #ifdef HAVE_LIBGDBM /* close the database - resuming sessions */ @@ -190,21 +190,24 @@ int gnutls_deinit(GNUTLS_STATE state) gnutls_sfree_datum( &state->cipher_specs.server_write_key); gnutls_sfree_datum( &state->cipher_specs.client_write_key); - _gnutls_mpi_release(&state->gnutls_key->KEY); - _gnutls_mpi_release(&state->gnutls_key->client_Y); - _gnutls_mpi_release(&state->gnutls_key->client_p); - _gnutls_mpi_release(&state->gnutls_key->client_g); + if (state->gnutls_key != NULL) { + _gnutls_mpi_release(&state->gnutls_key->KEY); + _gnutls_mpi_release(&state->gnutls_key->client_Y); + _gnutls_mpi_release(&state->gnutls_key->client_p); + _gnutls_mpi_release(&state->gnutls_key->client_g); - _gnutls_mpi_release(&state->gnutls_key->u); - _gnutls_mpi_release(&state->gnutls_key->a); - _gnutls_mpi_release(&state->gnutls_key->x); - _gnutls_mpi_release(&state->gnutls_key->A); - _gnutls_mpi_release(&state->gnutls_key->B); - _gnutls_mpi_release(&state->gnutls_key->b); + _gnutls_mpi_release(&state->gnutls_key->u); + _gnutls_mpi_release(&state->gnutls_key->a); + _gnutls_mpi_release(&state->gnutls_key->x); + _gnutls_mpi_release(&state->gnutls_key->A); + _gnutls_mpi_release(&state->gnutls_key->B); + _gnutls_mpi_release(&state->gnutls_key->b); - _gnutls_mpi_release(&state->gnutls_key->dh_secret); - _gnutls_free(state->gnutls_key); + _gnutls_mpi_release(&state->gnutls_key->dh_secret); + _gnutls_free(state->gnutls_key); + state->gnutls_key = NULL; + } /* free priorities */ _gnutls_free(state->gnutls_internals.MACAlgorithmPriority.algorithm_priority); @@ -246,7 +249,7 @@ static svoid *gnutls_P_hash( MACAlgorithm algorithm, opaque * secret, int secret int i = 0, times, how, blocksize, A_size; opaque final[20], Atmp[MAX_SEED_SIZE]; - if (seed_size > MAX_SEED_SIZE) { + if (seed_size > MAX_SEED_SIZE || total_bytes<=0) { gnutls_assert(); return NULL; } diff --git a/lib/gnutls_session.c b/lib/gnutls_session.c index 8474d59c3d..8e98641e60 100644 --- a/lib/gnutls_session.c +++ b/lib/gnutls_session.c @@ -20,8 +20,9 @@ #include "gnutls_int.h" #include "gnutls_errors.h" #include "debug.h" +#include <gnutls_session_pack.h> -#define SESSION_SIZE sizeof(SecurityParameters) + sizeof(state->gnutls_key->auth_info_size) + state->gnutls_key->auth_info_size +#define SESSION_SIZE _gnutls_session_size( state) /** * gnutls_get_current_session - Returns all session parameters. @@ -38,6 +39,9 @@ **/ int gnutls_get_current_session( GNUTLS_STATE state, opaque* session, int *session_size) { + gnutls_datum psession; + int ret; + if (*session_size < SESSION_SIZE || session==NULL) { *session_size = SESSION_SIZE; session = NULL; /* return with the new session_size value */ @@ -48,10 +52,15 @@ int gnutls_get_current_session( GNUTLS_STATE state, opaque* session, int *sessio if (session==NULL) { return 0; } - memcpy( session, &state->security_parameters, sizeof(SecurityParameters)); - memcpy( &session[sizeof(SecurityParameters)], &state->gnutls_key->auth_info_size, sizeof(state->gnutls_key->auth_info_size)); - memcpy( &session[sizeof(state->gnutls_key->auth_info_size)+sizeof(SecurityParameters)], - state->gnutls_key->auth_info, state->gnutls_key->auth_info_size); + + psession.data = session; + + ret = _gnutls_session_pack( state, &psession); + if (ret< 0) { + gnutls_assert(); + return ret; + } + *session_size = psession.size; return 0; } @@ -97,43 +106,15 @@ int gnutls_get_current_session_id( GNUTLS_STATE state, void* session, int *sessi * performed. **/ int gnutls_set_current_session( GNUTLS_STATE state, opaque* session, int session_size) { - int auth_info_size; - int timestamp = time(0); - SecurityParameters sp; + int ret; + gnutls_datum psession = { session, session_size }; - if ( (session_size - sizeof(SecurityParameters)) - >= sizeof(state->gnutls_key->auth_info_size)) { /* have more data */ - auth_info_size = *((int*)&session[sizeof(SecurityParameters)]); - } else { - auth_info_size = 0; - gnutls_assert(); - return GNUTLS_E_DB_ERROR; - } - if (session_size < sizeof(SecurityParameters)) { + ret = _gnutls_session_unpack( state, &psession); + if (ret < 0) { gnutls_assert(); - return GNUTLS_E_UNIMPLEMENTED_FEATURE; + return ret; } - memcpy( &sp, session, sizeof(SecurityParameters)); - if ( timestamp - sp.timestamp <= state->gnutls_internals.expire_time - && sp.timestamp <= timestamp) { - - memcpy( &state->gnutls_internals.resumed_security_parameters, &sp, sizeof(SecurityParameters)); - if (auth_info_size > 0) { - state->gnutls_key->auth_info = gnutls_malloc(auth_info_size); - if (state->gnutls_key->auth_info==NULL) { - gnutls_assert(); - return GNUTLS_E_MEMORY_ERROR; - } - state->gnutls_key->auth_info_size = auth_info_size; - memcpy( state->gnutls_key->auth_info, &session[sizeof(SecurityParameters)+sizeof(state->gnutls_key->auth_info_size)], auth_info_size); - } else { /* set to null */ - state->gnutls_key->auth_info_size = 0; - state->gnutls_key->auth_info = NULL; - } - } else { - return GNUTLS_E_EXPIRED; - } return 0; } diff --git a/lib/gnutls_session_pack.c b/lib/gnutls_session_pack.c new file mode 100644 index 0000000000..38396d14de --- /dev/null +++ b/lib/gnutls_session_pack.c @@ -0,0 +1,344 @@ +/* + * Copyright (C) 2000 Nikos Mavroyanopoulos + * + * This file is part of GNUTLS. + * + * GNUTLS is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GNUTLS is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ +#include <gnutls_int.h> +#include <auth_srp.h> +#include <auth_anon.h> +#include <auth_x509.h> +#include <gnutls_errors.h> +#include <gnutls_auth_int.h> +#include <gnutls_session_pack.h> +#include <gnutls_datum.h> +#include <gnutls_num.h> + +#define PACK_HEADER_SIZE 1 +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(); + + +/* Since auth_info structures contain malloced data, this function + * is required in order to pack these structures in a vector in + * order to store them to the DB. + */ +int _gnutls_session_pack(GNUTLS_STATE state, gnutls_datum * packed_session) +{ + uint32 pack_size; + int ret; + + if (packed_session==NULL) { + gnutls_assert(); + 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) + return GNUTLS_E_INVALID_PARAMETERS; + + pack_size = sizeof(SRP_SERVER_AUTH_INFO_INT); + packed_session->size = + PACK_HEADER_SIZE + pack_size + sizeof(uint32); + + packed_session->data[0] = GNUTLS_SRP; + 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)); + + } + break; + case GNUTLS_ANON:{ + ANON_CLIENT_AUTH_INFO info = + _gnutls_get_auth_info(state); + if (info == NULL) + return GNUTLS_E_INVALID_PARAMETERS; + + pack_size = sizeof(ANON_CLIENT_AUTH_INFO_INT); + packed_session->size = + PACK_HEADER_SIZE + pack_size + sizeof(uint32); + + packed_session->data[0] = GNUTLS_ANON; + 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)); + + } + break; + case GNUTLS_X509PKI:{ + X509PKI_AUTH_INFO info = + _gnutls_get_auth_info(state); + if (info == NULL) + return GNUTLS_E_INVALID_PARAMETERS; + + ret = + _gnutls_pack_x509pki_auth_info(info, + packed_session); + if (ret < 0) { + gnutls_assert(); + return ret; + } + } + break; + default: + return GNUTLS_E_UNIMPLEMENTED_FEATURE; + + } + + /* Auth_info structures copied. Now copy SecurityParameters. + */ + packed_session->size += sizeof(SecurityParameters)+sizeof(uint32); + + WRITEuint32( sizeof(SecurityParameters), &packed_session->data[packed_session->size - sizeof(SecurityParameters) - sizeof(uint32)]); + memcpy(&packed_session-> + data[packed_session->size - sizeof(SecurityParameters)], + &state->security_parameters, sizeof(SecurityParameters)); + + return 0; +} + +/* Returns the size needed to hold the current session. + */ +int _gnutls_session_size( GNUTLS_STATE state) +{ + uint32 pack_size; + + pack_size = PACK_HEADER_SIZE + sizeof(uint32); + + switch ( gnutls_get_auth_type(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); + } + + /* Auth_info structures copied. Now copy SecurityParameters. + */ + pack_size += sizeof(SecurityParameters) + sizeof(uint32); + + return pack_size; +} + +int _gnutls_session_unpack(GNUTLS_STATE state, + const gnutls_datum * packed_session) +{ + uint32 pack_size; + int ret; + uint32 timestamp = time(0); + SecurityParameters sp; + + if (packed_session==NULL || packed_session->size == 0) { + gnutls_assert(); + return GNUTLS_E_UNIMPLEMENTED_FEATURE; + } + + if (state->gnutls_key->auth_info != NULL) { + _gnutls_free_auth_info( state); + } + + 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(); + return GNUTLS_E_DB_ERROR; + } + + state->gnutls_key->auth_info = + gnutls_calloc(1, + sizeof + (SRP_SERVER_AUTH_INFO_INT)); + if (state->gnutls_key->auth_info == NULL) + return GNUTLS_E_MEMORY_ERROR; + state->gnutls_key->auth_info_size = + sizeof(SRP_SERVER_AUTH_INFO_INT); + + + memcpy(state->gnutls_key->auth_info, + &packed_session->data[PACK_HEADER_SIZE + + sizeof(uint32)], + sizeof(SRP_SERVER_AUTH_INFO_INT)); + } + break; + case GNUTLS_ANON:{ + pack_size = + READuint32(&packed_session-> + data[PACK_HEADER_SIZE]); + + if (pack_size == 0) break; + + if (pack_size != sizeof(ANON_CLIENT_AUTH_INFO_INT)) { + gnutls_assert(); + return GNUTLS_E_DB_ERROR; + } + + state->gnutls_key->auth_info = + gnutls_calloc(1, + sizeof + (ANON_CLIENT_AUTH_INFO_INT)); + if (state->gnutls_key->auth_info == NULL) + return GNUTLS_E_MEMORY_ERROR; + state->gnutls_key->auth_info_size = + sizeof(ANON_CLIENT_AUTH_INFO_INT); + + memcpy(state->gnutls_key->auth_info, + &packed_session->data[PACK_HEADER_SIZE], + sizeof(ANON_CLIENT_AUTH_INFO_INT)); + } + break; + case GNUTLS_X509PKI:{ + pack_size = + READuint32(&packed_session-> + data[PACK_HEADER_SIZE]); + + if (pack_size == 0) break; + + if (pack_size < sizeof(X509PKI_AUTH_INFO_INT)) { + gnutls_assert(); + return GNUTLS_E_DB_ERROR; + } + + state->gnutls_key->auth_info = + gnutls_calloc(1, + sizeof(X509PKI_AUTH_INFO_INT)); + if (state->gnutls_key->auth_info == NULL) + return GNUTLS_E_MEMORY_ERROR; + state->gnutls_key->auth_info_size = + sizeof(X509PKI_AUTH_INFO_INT); + + ret = + _gnutls_unpack_x509pki_auth_info(state-> + gnutls_key-> + auth_info, + packed_session); + if (ret < 0) { + gnutls_assert(); + return ret; + } + + pack_size += ret; + + } + break; + default: + return GNUTLS_E_UNIMPLEMENTED_FEATURE; + + } + + state->gnutls_key->auth_info_type = packed_session->data[0]; + + /* Auth_info structures copied. Now copy SecurityParameters. + */ + ret = + READuint32(&packed_session-> + data[PACK_HEADER_SIZE + sizeof(uint32) + + pack_size]); + + if (ret != sizeof(SecurityParameters)) { + gnutls_assert(); + return GNUTLS_E_DB_ERROR; + } + memcpy(&sp, &packed_session->data[PACK_HEADER_SIZE + + 2 * sizeof(uint32) + pack_size], + sizeof(SecurityParameters)); + + if ( timestamp - sp.timestamp <= state->gnutls_internals.expire_time + && sp.timestamp <= timestamp) { + + memcpy( &state->gnutls_internals.resumed_security_parameters, &sp, sizeof(SecurityParameters)); + } else { + _gnutls_free_auth_info( state); + + return GNUTLS_E_EXPIRED; + } + + + return 0; +} + +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); + + packed_session->data[0] = GNUTLS_X509PKI; + WRITEuint32(pack_size, &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); + + return 0; +} + +static int _gnutls_pack_x509pki_auth_info_size( GNUTLS_STATE state) +{ + X509PKI_AUTH_INFO info = + _gnutls_get_auth_info(state); + uint32 pack_size = sizeof(X509PKI_AUTH_INFO_INT); + + if (info == NULL) + return 0; + + return pack_size + PACK_HEADER_SIZE + sizeof(uint32) + info->raw_certificate.size; +} + + +int _gnutls_unpack_x509pki_auth_info(X509PKI_AUTH_INFO info, + const gnutls_datum * packed_session) +{ +int ret; + + 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) { + gnutls_assert(); + return ret; + } + } + return 0; +} diff --git a/lib/gnutls_session_pack.h b/lib/gnutls_session_pack.h new file mode 100644 index 0000000000..580ace5cdb --- /dev/null +++ b/lib/gnutls_session_pack.h @@ -0,0 +1,3 @@ +int _gnutls_session_pack( GNUTLS_STATE state, gnutls_datum* packed_session); +int _gnutls_session_unpack( GNUTLS_STATE state, const gnutls_datum* packed_session); +int _gnutls_session_size(GNUTLS_STATE state); diff --git a/lib/gnutls_ui.c b/lib/gnutls_ui.c index 046d028e9c..7bb796b275 100644 --- a/lib/gnutls_ui.c +++ b/lib/gnutls_ui.c @@ -145,7 +145,7 @@ X509PKI_AUTH_INFO info; CertificateStatus gnutls_x509pki_get_peer_certificate_status( GNUTLS_STATE state) { X509PKI_AUTH_INFO info; - CHECK_AUTH(GNUTLS_X509PKI, GNUTLS_E_INVALID_REQUEST); + CHECK_AUTH(GNUTLS_X509PKI, GNUTLS_CERT_NONE); info = _gnutls_get_auth_info(state); if (info==NULL) return GNUTLS_CERT_NONE; @@ -153,6 +153,25 @@ X509PKI_AUTH_INFO info; } /** + * 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. + * Returns NULL in case of an error, or if no certificate was sent. + * + **/ +const gnutls_datum * gnutls_x509pki_get_peer_certificate( 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->raw_certificate; +} + +/** * gnutls_x509pki_get_peer_certificate_version - This function returns the peer's certificate version * @state: is a gnutls state * diff --git a/lib/gnutls_ui.h b/lib/gnutls_ui.h index e8d71fb178..27784f24d4 100644 --- a/lib/gnutls_ui.h +++ b/lib/gnutls_ui.h @@ -61,6 +61,7 @@ int gnutls_x509pki_set_cert_request( GNUTLS_STATE, CertificateRequest); int gnutls_x509pki_get_certificate_request_status( GNUTLS_STATE); const gnutls_DN* gnutls_x509pki_get_peer_dn( GNUTLS_STATE); +const gnutls_datum* gnutls_x509pki_get_peer_certificate( GNUTLS_STATE); const gnutls_DN* gnutls_x509pki_get_issuer_dn( GNUTLS_STATE); CertificateStatus gnutls_x509pki_get_peer_certificate_status( GNUTLS_STATE); int gnutls_x509pki_get_peer_certificate_version( GNUTLS_STATE); @@ -76,6 +77,7 @@ int gnutls_x509pki_get_dh_bits( GNUTLS_STATE); #define gnutls_x509pki_server_get_peer_dn gnutls_x509pki_get_peer_dn #define gnutls_x509pki_server_get_issuer_dn gnutls_x509pki_get_issuer_dn #define gnutls_x509pki_server_get_peer_certificate_status gnutls_x509pki_get_peer_certificate_status +#define gnutls_x509pki_server_get_peer_certificate gnutls_x509pki_get_peer_certificate #define gnutls_x509pki_server_get_peer_certificate_version gnutls_x509pki_get_peer_certificate_version #define gnutls_x509pki_server_get_peer_certificate_activation_time gnutls_x509pki_get_peer_certificate_activation_time #define gnutls_x509pki_server_get_peer_certificate_expiration_time gnutls_x509pki_get_peer_certificate_expiration_time @@ -85,6 +87,7 @@ int gnutls_x509pki_get_dh_bits( GNUTLS_STATE); #define gnutls_x509pki_client_get_peer_dn gnutls_x509pki_get_peer_dn #define gnutls_x509pki_client_get_issuer_dn gnutls_x509pki_get_issuer_dn #define gnutls_x509pki_client_get_peer_certificate_status gnutls_x509pki_get_peer_certificate_status +#define gnutls_x509pki_client_get_peer_certificate gnutls_x509pki_get_peer_certificate #define gnutls_x509pki_client_get_peer_certificate_version gnutls_x509pki_get_peer_certificate_version #define gnutls_x509pki_client_get_peer_certificate_activation_time gnutls_x509pki_get_peer_certificate_activation_time #define gnutls_x509pki_client_get_peer_certificate_expiration_time gnutls_x509pki_get_peer_certificate_expiration_time |