diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2013-01-27 18:17:35 +0100 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2013-01-27 18:18:57 +0100 |
commit | 02ebe6b5143e39eb91b382ae6c301fe88dec8c8a (patch) | |
tree | 3fbe01fbf84658c08b1ce960d9b1af074ac55a70 | |
parent | b062201a4304c5759c678eeda44755fbf0cd8af1 (diff) | |
download | gnutls-02ebe6b5143e39eb91b382ae6c301fe88dec8c8a.tar.gz |
Added new interface.
-rw-r--r-- | NEWS | 20 | ||||
-rw-r--r-- | lib/Makefile.am | 4 | ||||
-rw-r--r-- | lib/gnutls_cert.c | 5 | ||||
-rw-r--r-- | lib/gnutls_errors.c | 2 | ||||
-rw-r--r-- | lib/includes/Makefile.am | 2 | ||||
-rw-r--r-- | lib/includes/gnutls/gnutls.h.in | 3 | ||||
-rw-r--r-- | lib/includes/gnutls/xssl.h (renamed from lib/includes/gnutls/sbuf.h) | 65 | ||||
-rw-r--r-- | lib/libgnutls.map | 25 | ||||
-rw-r--r-- | lib/xssl.c (renamed from lib/sbuf.c) | 382 | ||||
-rw-r--r-- | lib/xssl.h (renamed from lib/sbuf.h) | 7 | ||||
-rw-r--r-- | lib/xssl_getline.c (renamed from lib/sbuf_getline.c) | 12 | ||||
-rw-r--r-- | tests/Makefile.am | 2 | ||||
-rw-r--r-- | tests/mini-sbuf.c | 204 | ||||
-rw-r--r-- | tests/mini-xssl.c | 406 |
14 files changed, 703 insertions, 436 deletions
@@ -37,13 +37,6 @@ extension. Whether length-hiding can be used on a given session can be checked u ** API and ABI modifications: gnutls_record_set_timeout: Added gnutls_record_get_random_padding_status: Added -gnutls_sbuf_deinit: Added -gnutls_sbuf_init: Added -gnutls_sbuf_flush: Added -gnutls_sbuf_write: Added -gnutls_sbuf_getdelim: Added -gnutls_sbuf_read: Added -gnutls_sbuf_handshake: Added gnutls_x509_crt_set_dn: Added gnutls_x509_crt_set_issuer_dn: Added gnutls_x509_crq_set_dn: Added @@ -55,6 +48,19 @@ gnutls_record_send_range: Added gnutls_record_set_max_empty_records: Added gnutls_record_can_use_length_hiding: Added gnutls_rnd_refresh: Added +xssl_deinit: Added +xssl_flush: Added +xssl_read: Added +xssl_getdelim: Added +xssl_write: Added +xssl_printf: Added +xssl_sinit: Added +xssl_client_init: Added +xssl_server_init: Added +xssl_get_session: Added +xssl_get_verify_status: Added +xssl_cred_init: Added +xssl_cred_deinit: Added GNUTLS_SEC_PARAM_EXPORT: Added GNUTLS_SEC_PARAM_VERY_WEAK: Added diff --git a/lib/Makefile.am b/lib/Makefile.am index 70d23f3a73..b313120442 100644 --- a/lib/Makefile.am +++ b/lib/Makefile.am @@ -78,7 +78,7 @@ COBJECTS = gnutls_range.c gnutls_record.c \ gnutls_rsa_export.c gnutls_helper.c gnutls_supplemental.c \ random.c crypto-api.c gnutls_privkey.c gnutls_pcert.c \ gnutls_pubkey.c locks.c gnutls_dtls.c system_override.c \ - crypto-backend.c verify-tofu.c pin.c tpm.c sbuf.c sbuf_getline.c + crypto-backend.c verify-tofu.c pin.c tpm.c xssl.c xssl_getline.c if ENABLE_PKCS11 COBJECTS += pkcs11.c pkcs11_privkey.c pkcs11_write.c pkcs11_secret.c @@ -100,7 +100,7 @@ HFILES = abstract_int.h debug.h gnutls_compress.h gnutls_cipher.h \ gnutls_state.h gnutls_x509.h crypto-backend.h \ gnutls_rsa_export.h gnutls_srp.h auth/srp.h auth/srp_passwd.h \ gnutls_helper.h gnutls_supplemental.h crypto.h random.h system.h\ - locks.h gnutls_mbuffers.h gnutls_ecc.h pin.h + locks.h gnutls_mbuffers.h gnutls_ecc.h pin.h xssl.h if ENABLE_PKCS11 HFILES += pkcs11_int.h diff --git a/lib/gnutls_cert.c b/lib/gnutls_cert.c index c451ef5c59..d43a5fb8ec 100644 --- a/lib/gnutls_cert.c +++ b/lib/gnutls_cert.c @@ -943,7 +943,10 @@ gnutls_certificate_verification_status_print (unsigned int status, if (type == GNUTLS_CRT_X509) { if (status & GNUTLS_CERT_REVOKED) - _gnutls_buffer_append_str (&str, _("The certificate chain revoked. ")); + _gnutls_buffer_append_str (&str, _("The certificate chain is revoked. ")); + + if (status & GNUTLS_CERT_MISMATCH) + _gnutls_buffer_append_str (&str, _("The certificate doesn't match the local copy (TOFU). ")); if (status & GNUTLS_CERT_REVOCATION_DATA_SUPERSEDED) _gnutls_buffer_append_str (&str, _("The revocation data are old and have been superseded. ")); diff --git a/lib/gnutls_errors.c b/lib/gnutls_errors.c index 95c2b5ac24..6bef39a47f 100644 --- a/lib/gnutls_errors.c +++ b/lib/gnutls_errors.c @@ -154,6 +154,8 @@ static const gnutls_error_entry error_algorithms[] = { GNUTLS_E_RECORD_LIMIT_REACHED, 1), ERROR_ENTRY (N_("Error in the certificate."), GNUTLS_E_CERTIFICATE_ERROR, 1), + ERROR_ENTRY (N_("Could not authenticate peer."), GNUTLS_E_AUTH_ERROR, + 1), ERROR_ENTRY (N_("Unknown Subject Alternative name in X.509 certificate."), GNUTLS_E_X509_UNKNOWN_SAN, 1), diff --git a/lib/includes/Makefile.am b/lib/includes/Makefile.am index bd48c0cc44..2fb86094c6 100644 --- a/lib/includes/Makefile.am +++ b/lib/includes/Makefile.am @@ -21,7 +21,7 @@ nobase_include_HEADERS = gnutls/x509.h gnutls/pkcs12.h gnutls/compat.h \ gnutls/openpgp.h gnutls/crypto.h gnutls/pkcs11.h \ gnutls/abstract.h gnutls/dtls.h gnutls/ocsp.h gnutls/tpm.h \ - gnutls/sbuf.h + gnutls/xssl.h if ENABLE_CXX nobase_include_HEADERS += gnutls/gnutlsxx.h diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in index f09046687e..38182880e1 100644 --- a/lib/includes/gnutls/gnutls.h.in +++ b/lib/includes/gnutls/gnutls.h.in @@ -450,6 +450,7 @@ extern "C" * @GNUTLS_CERT_REVOCATION_DATA_SUPERSEDED: The revocation data are old and have been superseded. * @GNUTLS_CERT_REVOCATION_DATA_ISSUED_IN_FUTURE: The revocation data have a future issue date. * @GNUTLS_CERT_UNEXPECTED_OWNER: The owner is not the expected one. + * @GNUTLS_CERT_MISMATCH: The certificate presented isn't the expected one (TOFU) * * Enumeration of certificate status codes. Note that the status * bits may have different meanings in OpenPGP keys and X.509 @@ -469,6 +470,7 @@ extern "C" GNUTLS_CERT_UNEXPECTED_OWNER = 1<<14, GNUTLS_CERT_REVOCATION_DATA_ISSUED_IN_FUTURE = 1<<15, GNUTLS_CERT_SIGNER_CONSTRAINTS_FAILURE = 1<<16, + GNUTLS_CERT_MISMATCH = 1<<17, } gnutls_certificate_status_t; /** @@ -2149,6 +2151,7 @@ typedef int (*gnutls_pin_callback_t) (void *userdata, int attempt, #define GNUTLS_E_NO_CERTIFICATE_STATUS -340 #define GNUTLS_E_OCSP_RESPONSE_ERROR -341 #define GNUTLS_E_RANDOM_DEVICE_ERROR -342 +#define GNUTLS_E_AUTH_ERROR -343 #define GNUTLS_E_UNIMPLEMENTED_FEATURE -1250 diff --git a/lib/includes/gnutls/sbuf.h b/lib/includes/gnutls/xssl.h index a629949aa6..a71bec1901 100644 --- a/lib/includes/gnutls/sbuf.h +++ b/lib/includes/gnutls/xssl.h @@ -24,45 +24,46 @@ #include <gnutls/gnutls.h> /* Buffered session I/O */ -typedef struct gnutls_sbuf_st *gnutls_sbuf_t; -typedef struct gnutls_credentials_st *gnutls_credentials_t; +typedef struct xssl_st *xssl_t; +typedef struct xssl_cred_st *xssl_cred_t; -ssize_t gnutls_sbuf_printf (gnutls_sbuf_t sb, const char *fmt, ...) +ssize_t xssl_printf (xssl_t sb, const char *fmt, ...) #ifdef __GNUC__ __attribute__ ((format (printf, 2, 3))) #endif ; -ssize_t gnutls_sbuf_write (gnutls_sbuf_t sb, const void *data, +ssize_t xssl_write (xssl_t sb, const void *data, size_t data_size); -ssize_t gnutls_sbuf_flush (gnutls_sbuf_t sb); +ssize_t xssl_flush (xssl_t sb); -int gnutls_sbuf_handshake(gnutls_sbuf_t sb); -ssize_t gnutls_sbuf_read(gnutls_sbuf_t sb, void* data, size_t data_size); +ssize_t xssl_read(xssl_t sb, void* data, size_t data_size); ssize_t -gnutls_sbuf_getdelim (gnutls_sbuf_t sbuf, char **lineptr, size_t *n, int delimiter); +xssl_getdelim (xssl_t sbuf, char **lineptr, size_t *n, int delimiter); -#define gnutls_sbuf_getline(sbuf, ptr, n) gnutls_sbuf_getdelim(sbuf, ptr, n, '\n') +#define xssl_getline(sbuf, ptr, n) xssl_getdelim(sbuf, ptr, n, '\n') -void gnutls_sbuf_deinit(gnutls_sbuf_t sb); +void xssl_deinit(xssl_t sb); -#define GNUTLS_SBUF_WRITE_FLUSHES 1 -int gnutls_sbuf_sinit (gnutls_sbuf_t * isb, gnutls_session_t session, +#define GNUTLS_SBUF_WRITE_FLUSHES (1<<0) +int xssl_sinit (xssl_t * isb, gnutls_session_t session, unsigned int flags); -gnutls_session_t gnutls_sbuf_get_session(gnutls_sbuf_t sb); +gnutls_session_t xssl_get_session(xssl_t sb); -int gnutls_sbuf_client_init (gnutls_sbuf_t * isb, const char* hostname, +int xssl_client_init (xssl_t * isb, const char* hostname, const char* service, gnutls_transport_ptr fd, - const char* priority, gnutls_credentials_t cred, + const char* priority, xssl_cred_t cred, + unsigned int *status, unsigned int flags); -int gnutls_sbuf_server_init (gnutls_sbuf_t * isb, +int xssl_server_init (xssl_t * isb, gnutls_transport_ptr fd, - const char* priority, gnutls_credentials_t cred, + const char* priority, xssl_cred_t cred, + unsigned int *status, unsigned int flags); /* High level credential structures */ @@ -76,8 +77,9 @@ typedef enum typedef enum { - GNUTLS_CRED_FILE = 0, - GNUTLS_CRED_MEM = 1, + GNUTLS_CINPUT_TYPE_FILE = 0, + GNUTLS_CINPUT_TYPE_MEM = 1, + GNUTLS_CINPUT_TYPE_PIN_FUNC = 2, } gnutls_cinput_type_t; typedef enum @@ -85,24 +87,33 @@ typedef enum GNUTLS_CINPUT_CAS = 1, GNUTLS_CINPUT_CRLS = 2, GNUTLS_CINPUT_TOFU_DB = 3, + GNUTLS_CINPUT_KEYPAIR = 4, } gnutls_cinput_contents_t; typedef struct gnutls_cinput_st { gnutls_cinput_type_t type; - gnutls_x509_crt_fmt_t fmt; /* if applicable */ gnutls_cinput_contents_t contents; + gnutls_x509_crt_fmt_t fmt; /* if applicable */ + union { + gnutls_pin_callback_t pin_fn; const char* file; gnutls_datum_t mem; - } i; -} gnutls_cinput_st; + } i1; -int gnutls_credentials_init (gnutls_credentials_t* cred); -void gnutls_credentials_deinit (gnutls_credentials_t cred); + union { + void* udata; + const char* file; + gnutls_datum_t mem; + } i2; + + unsigned long future_pad[8]; +} gnutls_cinput_st; -int gnutls_credentials_set_trust (gnutls_credentials_t cred, unsigned vflags, - gnutls_cinput_st* aux, - unsigned aux_size); +int xssl_cred_init (xssl_cred_t *c, unsigned vflags, + gnutls_cinput_st* aux, + unsigned aux_size); +void xssl_cred_deinit (xssl_cred_t cred); #endif /* GNUTLS_SBUF_H */ diff --git a/lib/libgnutls.map b/lib/libgnutls.map index 8eca27684f..d44d76d79d 100644 --- a/lib/libgnutls.map +++ b/lib/libgnutls.map @@ -885,18 +885,19 @@ GNUTLS_3_1_0 { gnutls_record_set_max_empty_records; gnutls_range_split; gnutls_record_send_range; - gnutls_sbuf_deinit; - gnutls_sbuf_flush; - gnutls_sbuf_read; - gnutls_sbuf_getdelim; - gnutls_sbuf_write; - gnutls_sbuf_printf; - gnutls_sbuf_sinit; - gnutls_sbuf_client_init; - gnutls_sbuf_get_session; - gnutls_credentials_init; - gnutls_credentials_deinit; - gnutls_credentials_set_trust; + xssl_deinit; + xssl_flush; + xssl_read; + xssl_getdelim; + xssl_write; + xssl_printf; + xssl_sinit; + xssl_client_init; + xssl_server_init; + xssl_get_session; + xssl_get_verify_status; + xssl_cred_init; + xssl_cred_deinit; } GNUTLS_3_0_0; GNUTLS_PRIVATE { diff --git a/lib/sbuf.c b/lib/xssl.c index 3b9efa4d1d..61555591d8 100644 --- a/lib/sbuf.c +++ b/lib/xssl.c @@ -23,94 +23,46 @@ #include <gnutls_int.h> #include <gnutls_errors.h> #include <gnutls_num.h> -#include <gnutls/sbuf.h> +#include <gnutls/xssl.h> +#include <auth/cert.h> -#include <sbuf.h> +#include <xssl.h> /** - * gnutls_sbuf_sinit: - * @isb: is a pointer to a #gnutls_sbuf_t structure. - * @session: a GnuTLS session - * @flags: should be zero or %GNUTLS_SBUF_WRITE_FLUSHES - * - * This function initializes a #gnutls_sbuf_t structure associated - * with the provided session. If the flag %GNUTLS_SBUF_WRITE_FLUSHES - * is set then gnutls_sbuf_queue() will flush when the maximum - * data size for a record is reached. - * - * Returns: %GNUTLS_E_SUCCESS on success, or an error code. - * - * Since: 3.1.7 - **/ -int gnutls_sbuf_sinit (gnutls_sbuf_t * isb, gnutls_session_t session, - unsigned int flags) -{ -struct gnutls_sbuf_st* sb; - - sb = gnutls_malloc(sizeof(*sb)); - if (sb == NULL) - return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); - - _gnutls_buffer_init(&sb->buf); - sb->session = session; - sb->flags = flags; - - *isb = sb; - - return 0; -} - - -/** - * gnutls_credentials_deinit: - * @cred: is a #gnutls_credentials_t structure. + * xssl_cred_deinit: + * @cred: is a #xssl_cred_t structure. * - * This function deinitializes a #gnutls_credentials_t structure. + * This function deinitializes a #xssl_cred_t structure. * * Returns: %GNUTLS_E_SUCCESS on success, or an error code. * * Since: 3.1.7 **/ -void gnutls_credentials_deinit (gnutls_credentials_t cred) +void xssl_cred_deinit (xssl_cred_t cred) { if (cred->xcred) gnutls_certificate_free_credentials(cred->xcred); gnutls_free(cred); } -/** - * gnutls_credentials_init: - * @cred: is a pointer to a #gnutls_credentials_t structure. - * - * This function initializes a #gnutls_credentials_t structure. - * - * Returns: %GNUTLS_E_SUCCESS on success, or an error code. - * - * Since: 3.1.7 - **/ -int gnutls_credentials_init (gnutls_credentials_t* cred) -{ - *cred = gnutls_calloc(1, sizeof(*cred)); - if (*cred == NULL) - return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); - - return 0; -} static int _verify_certificate_callback (gnutls_session_t session) { unsigned int status; - gnutls_sbuf_t sb; + xssl_t sb; int ret, type; const char *hostname = NULL; const char *service = NULL; const char *tofu_file = NULL; - + sb = gnutls_session_get_ptr(session); if (sb == NULL) return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + if (sb->cred == NULL) + return gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS); + if (sb->server_name[0] != 0) hostname = sb->server_name; @@ -123,17 +75,20 @@ _verify_certificate_callback (gnutls_session_t session) /* This verification function uses the trusted CAs in the credentials * structure. So you must have installed one or more CA certificates. */ + sb->vstatus = 0; if (sb->cred->vflags & GNUTLS_VMETHOD_SYSTEM_CAS || sb->cred->vflags & GNUTLS_VMETHOD_GIVEN_CAS) { ret = gnutls_certificate_verify_peers3 (session, hostname, &status); if (ret < 0) - return gnutls_assert_val(GNUTLS_E_CERTIFICATE_ERROR); + return gnutls_assert_val(GNUTLS_E_AUTH_ERROR); + + sb->vstatus = status; if (status != 0) /* Certificate is not trusted */ - return gnutls_assert_val(GNUTLS_E_CERTIFICATE_ERROR); + return gnutls_assert_val(GNUTLS_E_AUTH_ERROR); } - if (sb->cred->vflags & GNUTLS_VMETHOD_TOFU) + if (hostname && sb->cred->vflags & GNUTLS_VMETHOD_TOFU) { const gnutls_datum_t *cert_list; unsigned int cert_list_size; @@ -143,7 +98,10 @@ _verify_certificate_callback (gnutls_session_t session) /* Do SSH verification */ cert_list = gnutls_certificate_get_peers (session, &cert_list_size); if (cert_list == NULL) - return gnutls_assert_val(GNUTLS_E_CERTIFICATE_ERROR); + { + sb->vstatus |= GNUTLS_CERT_INVALID; + return gnutls_assert_val(GNUTLS_E_AUTH_ERROR); + } /* service may be obtained alternatively using getservbyport() */ ret = gnutls_verify_stored_pubkey(tofu_file, NULL, hostname, service, @@ -155,9 +113,15 @@ _verify_certificate_callback (gnutls_session_t session) type, &cert_list[0], 0, 0); } else if (ret == GNUTLS_E_CERTIFICATE_KEY_MISMATCH) - return gnutls_assert_val(GNUTLS_E_CERTIFICATE_ERROR); + { + sb->vstatus |= GNUTLS_CERT_MISMATCH; + return gnutls_assert_val(GNUTLS_E_AUTH_ERROR); + } else if (ret < 0) - return gnutls_assert_val(ret); + { + sb->vstatus |= GNUTLS_CERT_INVALID; + return gnutls_assert_val(GNUTLS_E_AUTH_ERROR); + } } /* notify gnutls to continue handshake normally */ @@ -165,14 +129,14 @@ _verify_certificate_callback (gnutls_session_t session) } /** - * gnutls_credentials_set_trust: - * @cred: is a #gnutls_credentials_t structure. + * xssl_cred_init: + * @c: is a pointer to #xssl_cred_t structure. * @vflags: the requested peer verification methods * @aux: Auxilary data to input any required CA certificate etc. * @aux_size: the number of the auxillary data provided * * This function initializes X.509 certificates in - * a #gnutls_credentials_t structure. + * a #xssl_cred_t structure. * * The @ca_file and @crl_file are required only if @vflags includes * %GNUTLS_VMETHOD_GIVEN_CAS. The @tofu_file may be set if @@ -182,12 +146,20 @@ _verify_certificate_callback (gnutls_session_t session) * * Since: 3.1.7 **/ -int gnutls_credentials_set_trust (gnutls_credentials_t cred, unsigned vflags, - gnutls_cinput_st* aux, - unsigned aux_size) +int xssl_cred_init (xssl_cred_t *c, unsigned vflags, + gnutls_cinput_st* aux, + unsigned aux_size) { int ret; unsigned len, i; +xssl_cred_t cred; + + *c = gnutls_calloc(1, sizeof(*cred)); + if (*c == NULL) + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + + cred = *c; + cred->vflags = vflags; if (cred->xcred == NULL) { @@ -206,47 +178,75 @@ unsigned len, i; } } - if (vflags & GNUTLS_VMETHOD_GIVEN_CAS) + for (i=0;i<aux_size;i++) { - for (i=0;i<aux_size;i++) + if (aux[i].contents == GNUTLS_CINPUT_KEYPAIR) { - if (aux[i].contents == GNUTLS_CINPUT_CAS && aux[i].type == GNUTLS_CRED_FILE) - ret = gnutls_certificate_set_x509_trust_file(cred->xcred, aux[i].i.file, aux[i].fmt); - else if (aux[i].contents == GNUTLS_CINPUT_CAS && aux[i].type == GNUTLS_CRED_MEM) - ret = gnutls_certificate_set_x509_trust_mem(cred->xcred, &aux[i].i.mem, aux[i].fmt); - else if (aux[i].contents == GNUTLS_CINPUT_CRLS && aux[i].type == GNUTLS_CRED_FILE) - ret = gnutls_certificate_set_x509_crl_file(cred->xcred, aux[i].i.file, aux[i].fmt); - else if (aux[i].contents == GNUTLS_CINPUT_CRLS && aux[i].type == GNUTLS_CRED_MEM) - ret = gnutls_certificate_set_x509_crl_mem(cred->xcred, &aux[i].i.mem, aux[i].fmt); - else - ret = 0; + if (aux[i].type == GNUTLS_CINPUT_TYPE_FILE) + ret = gnutls_certificate_set_x509_key_file(cred->xcred, aux[i].i1.file, aux[i].i2.file, aux[i].fmt); + else if (aux[i].type == GNUTLS_CINPUT_TYPE_MEM) + ret = gnutls_certificate_set_x509_key_mem(cred->xcred, &aux[i].i1.mem, &aux[i].i2.mem, aux[i].fmt); + else if (aux[i].type == GNUTLS_CINPUT_TYPE_PIN_FUNC) + { + ret = 0; + gnutls_certificate_set_pin_function(cred->xcred, aux[i].i1.pin_fn, + aux[i].i2.udata); + } + if (ret < 0) { gnutls_assert(); goto fail1; } } - } + + if (aux[i].contents == GNUTLS_CINPUT_CAS && (vflags & GNUTLS_VMETHOD_GIVEN_CAS)) + { + if (aux[i].type == GNUTLS_CINPUT_TYPE_FILE) + ret = gnutls_certificate_set_x509_trust_file(cred->xcred, aux[i].i1.file, aux[i].fmt); + else + ret = gnutls_certificate_set_x509_trust_mem(cred->xcred, &aux[i].i1.mem, aux[i].fmt); - if (vflags & GNUTLS_VMETHOD_TOFU) - { - for (i=0;i<aux_size;i++) + if (ret < 0) + { + gnutls_assert(); + goto fail1; + } + } + + if (aux[i].contents == GNUTLS_CINPUT_CRLS && (vflags & GNUTLS_VMETHOD_GIVEN_CAS)) { - if (aux[i].contents == GNUTLS_CINPUT_TOFU_DB) + if (aux[i].type == GNUTLS_CINPUT_TYPE_FILE) + ret = gnutls_certificate_set_x509_crl_file(cred->xcred, aux[i].i1.file, aux[i].fmt); + else + ret = gnutls_certificate_set_x509_crl_mem(cred->xcred, &aux[i].i1.mem, aux[i].fmt); + + if (ret < 0) { - if (aux[i].type != GNUTLS_CRED_FILE) - { - ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); - goto fail1; - } - len = strlen(aux[i].i.file); - + gnutls_assert(); + goto fail1; + } + } + + if (aux[i].contents == GNUTLS_CINPUT_TOFU_DB && (vflags & GNUTLS_VMETHOD_TOFU)) + { + if (aux[i].type == GNUTLS_CINPUT_TYPE_FILE) + { + len = strlen(aux[i].i1.file); if (len >= sizeof(cred->tofu_file)) { ret = gnutls_assert_val(GNUTLS_E_INVALID_REQUEST); goto fail1; } - memcpy(cred->tofu_file, aux[i].i.file, len+1); + memcpy(cred->tofu_file, aux[i].i1.file, len+1); + } + else + ret = GNUTLS_E_INVALID_REQUEST; + + if (ret < 0) + { + gnutls_assert(); + goto fail1; } } } @@ -257,36 +257,74 @@ unsigned len, i; fail1: gnutls_certificate_free_credentials(cred->xcred); cred->xcred = NULL; + gnutls_free(*c); + return ret; } +/** + * xssl_sinit: + * @isb: is a pointer to a #xssl_t structure. + * @session: a GnuTLS session + * @flags: should be zero or %GNUTLS_SBUF_WRITE_FLUSHES + * + * This function initializes a #xssl_t structure associated + * with the provided session. If the flag %GNUTLS_SBUF_WRITE_FLUSHES + * is set then xssl_queue() will flush when the maximum + * data size for a record is reached. + * + * Returns: %GNUTLS_E_SUCCESS on success, or an error code. + * + * Since: 3.1.7 + **/ +int xssl_sinit (xssl_t * isb, gnutls_session_t session, + unsigned int flags) +{ +struct xssl_st* sb; + + sb = gnutls_calloc(1, sizeof(*sb)); + if (sb == NULL) + return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); + + _gnutls_buffer_init(&sb->buf); + sb->session = session; + sb->flags = flags; + + *isb = sb; + + return 0; +} /** - * gnutls_sbuf_client_init: - * @isb: is a pointer to a #gnutls_sbuf_t structure. + * xssl_client_init: + * @isb: is a pointer to a #xssl_t structure. * @hostname: The name of the host to connect to * @service: The name of the host to connect to * @fd: a socket descriptor * @priority: A priority string to use (use %NULL for default) * @cred: A credentials structure + * @status: An authentication failure status * @flags: should be zero or %GNUTLS_SBUF_WRITE_FLUSHES * - * This function initializes a #gnutls_sbuf_t structure. + * This function initializes a #xssl_t structure. * If the flag %GNUTLS_SBUF_WRITE_FLUSHES - * is set then gnutls_sbuf_queue() will flush when the maximum + * is set then xssl_queue() will flush when the maximum * data size for a record is reached. * + * If peer verification fails then %GNUTLS_E_AUTH_ERROR is returned. + * * Returns: %GNUTLS_E_SUCCESS on success, or an error code. * * Since: 3.1.7 **/ -int gnutls_sbuf_client_init (gnutls_sbuf_t * isb, const char* hostname, +int xssl_client_init (xssl_t * isb, const char* hostname, const char* service, gnutls_transport_ptr fd, - const char* priority, gnutls_credentials_t cred, + const char* priority, xssl_cred_t cred, + unsigned int *status, unsigned int flags) { -struct gnutls_sbuf_st* sb; +struct xssl_st* sb; gnutls_session_t session; int ret; unsigned len; @@ -298,12 +336,14 @@ unsigned len; sb = gnutls_calloc(1, sizeof(*sb)); if (sb == NULL) { + gnutls_deinit(session); ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); goto fail1; } _gnutls_buffer_init(&sb->buf); sb->session = session; sb->flags = flags; + sb->cred = cred; /* set session/handshake info */ @@ -354,15 +394,25 @@ unsigned len; gnutls_transport_set_ptr (session, fd); gnutls_session_set_ptr( session, sb); - + do { ret = gnutls_handshake(session); } while (ret < 0 && gnutls_error_is_fatal (ret) == 0); + if (status) *status = sb->vstatus; if (ret < 0) { + int ret2; + do + { + ret2 = gnutls_alert_send_appropriate(sb->session, ret); + } + while (ret2 < 0 && gnutls_error_is_fatal(ret2) == 0); + + return gnutls_assert_val(ret); + gnutls_assert(); goto fail1; } @@ -373,35 +423,36 @@ unsigned len; fail1: if (sb) - gnutls_sbuf_deinit(sb); - gnutls_deinit(session); + xssl_deinit(sb); return ret; } /** - * gnutls_sbuf_server_init: - * @isb: is a pointer to a #gnutls_sbuf_t structure. + * xssl_server_init: + * @isb: is a pointer to a #xssl_t structure. * @fd: a socket descriptor * @priority: A priority string to use (use %NULL for default) * @cred: A credentials structure + * @status: An authentication failure status * @flags: should be zero or %GNUTLS_SBUF_WRITE_FLUSHES * - * This function initializes a #gnutls_sbuf_t structure. + * This function initializes a #xssl_t structure. * If the flag %GNUTLS_SBUF_WRITE_FLUSHES - * is set then gnutls_sbuf_queue() will flush when the maximum + * is set then xssl_queue() will flush when the maximum * data size for a record is reached. * * Returns: %GNUTLS_E_SUCCESS on success, or an error code. * * Since: 3.1.7 **/ -int gnutls_sbuf_server_init (gnutls_sbuf_t * isb, +int xssl_server_init (xssl_t * isb, gnutls_transport_ptr fd, - const char* priority, gnutls_credentials_t cred, + const char* priority, xssl_cred_t cred, + unsigned int *status, unsigned int flags) { -struct gnutls_sbuf_st* sb; +struct xssl_st* sb; gnutls_session_t session; int ret; @@ -412,12 +463,14 @@ int ret; sb = gnutls_calloc(1, sizeof(*sb)); if (sb == NULL) { + gnutls_deinit(session); ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); goto fail1; } _gnutls_buffer_init(&sb->buf); sb->session = session; sb->flags = flags; + sb->cred = cred; /* set session/handshake info */ @@ -433,15 +486,25 @@ int ret; if (cred->xcred) { + if (cred->xcred->ncerts == 0 && cred->xcred->get_cert_callback2 == NULL) + { + ret = gnutls_assert_val(GNUTLS_E_INSUFFICIENT_CREDENTIALS); + goto fail1; + } + ret = gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, cred->xcred); if (ret < 0) { gnutls_assert(); goto fail1; } + } - gnutls_transport_set_ptr (session, fd); + if (cred->vflags & GNUTLS_VMETHOD_GIVEN_CAS) + gnutls_certificate_server_set_request( session, GNUTLS_CERT_REQUIRE); + + gnutls_transport_set_ptr( session, fd); gnutls_session_set_ptr( session, sb); do @@ -449,9 +512,19 @@ int ret; ret = gnutls_handshake(session); } while (ret < 0 && gnutls_error_is_fatal (ret) == 0); + if (status) *status = sb->vstatus; if (ret < 0) { + int ret2; + do + { + ret2 = gnutls_alert_send_appropriate(sb->session, ret); + } + while (ret2 < 0 && gnutls_error_is_fatal(ret2) == 0); + + return gnutls_assert_val(ret); + gnutls_assert(); goto fail1; } @@ -462,15 +535,14 @@ int ret; fail1: if (sb) - gnutls_sbuf_deinit(sb); - gnutls_deinit(session); + xssl_deinit(sb); return ret; } /** - * gnutls_sbuf_deinit: - * @sb: is a #gnutls_sbuf_t structure. + * xssl_deinit: + * @sb: is a #xssl_t structure. * * This function clears all buffers associated with the @sb * structure. The GnuTLS session associated with the structure @@ -478,7 +550,7 @@ fail1: * * Since: 3.1.7 **/ -void gnutls_sbuf_deinit(gnutls_sbuf_t sb) +void xssl_deinit(xssl_t sb) { if (sb->session) { @@ -490,14 +562,14 @@ void gnutls_sbuf_deinit(gnutls_sbuf_t sb) } /** - * gnutls_sbuf_write: - * @sb: is a #gnutls_sbuf_t structure. + * xssl_write: + * @sb: is a #xssl_t structure. * @data: contains the data to send * @data_size: is the length of the data * * This function is the buffered equivalent of gnutls_record_send(). * Instead of sending the data immediately the data are buffered - * until gnutls_sbuf_queue() is called, or if the flag %GNUTLS_SBUF_WRITE_FLUSHES + * until xssl_queue() is called, or if the flag %GNUTLS_SBUF_WRITE_FLUSHES * is set, until the number of bytes for a full record is reached. * * This function must only be used with blocking sockets. @@ -507,7 +579,7 @@ void gnutls_sbuf_deinit(gnutls_sbuf_t sb) * * Since: 3.1.7 **/ -ssize_t gnutls_sbuf_write (gnutls_sbuf_t sb, const void *data, +ssize_t xssl_write (xssl_t sb, const void *data, size_t data_size) { int ret; @@ -535,11 +607,11 @@ int ret; } /** - * gnutls_sbuf_printf: - * @sb: is a #gnutls_sbuf_t structure. + * xssl_printf: + * @sb: is a #xssl_t structure. * @fmt: printf-style format * - * This function allows writing to a %gnutls_sbuf_t using printf + * This function allows writing to a %xssl_t using printf * style arguments. * * This function must only be used with blocking sockets. @@ -549,7 +621,7 @@ int ret; * * Since: 3.1.7 **/ -ssize_t gnutls_sbuf_printf (gnutls_sbuf_t sb, const char *fmt, ...) +ssize_t xssl_printf (xssl_t sb, const char *fmt, ...) { int ret; va_list args; @@ -563,7 +635,7 @@ char* str; if (len < 0 || !str) return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR); - ret = gnutls_sbuf_write (sb, str, len); + ret = xssl_write (sb, str, len); gnutls_free(str); @@ -571,8 +643,8 @@ char* str; } /** - * gnutls_sbuf_flush: - * @sb: is a #gnutls_sbuf_t structure. + * xssl_flush: + * @sb: is a #xssl_t structure. * * This function flushes the buffer @sb. All the data stored are transmitted. * @@ -582,7 +654,7 @@ char* str; * * Since: 3.1.7 **/ -ssize_t gnutls_sbuf_flush (gnutls_sbuf_t sb) +ssize_t xssl_flush (xssl_t sb) { int ret; ssize_t total = 0; @@ -606,42 +678,8 @@ ssize_t total = 0; } /** - * gnutls_sbuf_handshake: - * @sb: is a #gnutls_sbuf_t structure. - * - * This function performs a handshake on the underlying session. - * Only fatal errors are returned by this function. - * - * Returns: On success, zero is returned, otherwise a negative error code. - * - * Since: 3.1.7 - **/ -int gnutls_sbuf_handshake(gnutls_sbuf_t sb) -{ -int ret, ret2; - - do - { - ret = gnutls_handshake(sb->session); - } - while (ret < 0 && gnutls_error_is_fatal(ret) == 0); - if (ret < 0) - { - do - { - ret2 = gnutls_alert_send_appropriate(sb->session, ret); - } - while (ret2 < 0 && gnutls_error_is_fatal(ret2) == 0); - - return gnutls_assert_val(ret); - } - - return 0; -} - -/** - * gnutls_sbuf_read: - * @sb: is a #gnutls_sbuf_t structure. + * xssl_read: + * @sb: is a #xssl_t structure. * @data: the buffer that the data will be read into * @data_size: the number of requested bytes * @@ -653,7 +691,7 @@ int ret, ret2; * * Since: 3.1.7 **/ -ssize_t gnutls_sbuf_read(gnutls_sbuf_t sb, void* data, size_t data_size) +ssize_t xssl_read(xssl_t sb, void* data, size_t data_size) { int ret; @@ -670,14 +708,14 @@ int ret; } /** - * gnutls_sbuf_get_session: - * @sb: is a #gnutls_sbuf_t structure. + * xssl_get_session: + * @sb: is a #xssl_t structure. * * Returns: The associated session or %NULL. * * Since: 3.1.7 **/ -gnutls_session_t gnutls_sbuf_get_session(gnutls_sbuf_t sb) +gnutls_session_t xssl_get_session(xssl_t sb) { return sb->session; } diff --git a/lib/sbuf.h b/lib/xssl.h index 44ea713604..416c36992f 100644 --- a/lib/sbuf.h +++ b/lib/xssl.h @@ -4,21 +4,22 @@ #include <gnutls_str.h> #include <gnutls/gnutls.h> -struct gnutls_credentials_st { +struct xssl_cred_st { gnutls_certificate_credentials_t xcred; char tofu_file[MAX_FILENAME]; unsigned vflags; }; -struct gnutls_sbuf_st { +struct xssl_st { gnutls_session_t session; gnutls_buffer_st buf; char server_name[MAX_SERVER_NAME_SIZE]; char service_name[MAX_SERVER_NAME_SIZE]; - gnutls_credentials_t cred; + xssl_cred_t cred; + unsigned int vstatus; /* the verification status reason */ unsigned int flags; }; diff --git a/lib/sbuf_getline.c b/lib/xssl_getline.c index 932d9dc96b..4f571b8bef 100644 --- a/lib/sbuf_getline.c +++ b/lib/xssl_getline.c @@ -22,16 +22,16 @@ #include <gnutls_int.h> #include <gnutls_errors.h> -#include <gnutls/sbuf.h> -#include <sbuf.h> +#include <gnutls/xssl.h> +#include <xssl.h> #ifndef SSIZE_MAX # define SSIZE_MAX ((ssize_t) (SIZE_MAX / 2)) #endif /** - * gnutls_sbuf_get_delim: - * @sb: is a #gnutls_sbuf_t structure. + * xssl_get_delim: + * @sb: is a #xssl_t structure. * @lineptr: a pointer. * @n: The size of @lineptr. * @delimiter: The delimiter to stop reading at. @@ -49,7 +49,7 @@ * Since: 3.1.7 **/ ssize_t -gnutls_sbuf_getdelim (gnutls_sbuf_t sbuf, char **lineptr, size_t *n, int delimiter) +xssl_getdelim (xssl_t sbuf, char **lineptr, size_t *n, int delimiter) { ssize_t result; size_t cur_len = 0; @@ -76,7 +76,7 @@ gnutls_sbuf_getdelim (gnutls_sbuf_t sbuf, char **lineptr, size_t *n, int delimit { char c; - result = gnutls_sbuf_read(sbuf, &c, 1); + result = xssl_read(sbuf, &c, 1); if (result < 0) { gnutls_assert(); diff --git a/tests/Makefile.am b/tests/Makefile.am index 26f7ab2a60..62f757ed6f 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -71,7 +71,7 @@ ctests = mini-deflate simple gc set_pkcs12_cred certder certuniqueid \ mini-termination mini-x509-cas mini-x509-2 pkcs12_simple \ mini-emsgsize-dtls mini-handshake-timeout chainverify-unsorted \ mini-dtls-heartbeat mini-x509-callbacks key-openssl \ - mini-dtls-srtp mini-dtls-record mini-sbuf + mini-dtls-srtp mini-dtls-record mini-xssl if ENABLE_OCSP ctests += ocsp diff --git a/tests/mini-sbuf.c b/tests/mini-sbuf.c deleted file mode 100644 index b4b6b13fbb..0000000000 --- a/tests/mini-sbuf.c +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (C) 2008-2012 Free Software Foundation, Inc. - * - * Author: Simon Josefsson - * - * 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 3 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 GnuTLS; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <gnutls/gnutls.h> -#include <gnutls/crypto.h> -#include <gnutls/sbuf.h> -#include "eagain-common.h" - -#include "utils.h" - -const char* side = ""; - -static void -tls_log_func (int level, const char *str) -{ - fprintf (stderr, "%s|<%d>| %s", side, level, str); -} - -#define MAX_BUF 60*1024 - -static unsigned char server_buf[MAX_BUF]; -static unsigned char client_buf[MAX_BUF]; - -#define LINE1 "hello there people\n" -#define LINE2 "how are you doing today, all well?\n" - -void -doit (void) -{ - /* Server stuff. */ - gnutls_anon_server_credentials_t s_anoncred; - const gnutls_datum_t p3 = { (unsigned char *) pkcs3, strlen (pkcs3) }; - static gnutls_dh_params_t dh_params; - gnutls_session_t server; - gnutls_sbuf_t ssbuf; - int sret = GNUTLS_E_AGAIN; - /* Client stuff. */ - gnutls_anon_client_credentials_t c_anoncred; - gnutls_session_t client; - int cret = GNUTLS_E_AGAIN; - /* Need to enable anonymous KX specifically. */ - int ret; - ssize_t left, spos, cpos; - char *abuf = NULL; - size_t abuf_size = 0; - - /* General init. */ - gnutls_global_init (); - gnutls_global_set_log_function (tls_log_func); - if (debug) - gnutls_global_set_log_level (4711); - - /* Init server */ - gnutls_anon_allocate_server_credentials (&s_anoncred); - gnutls_dh_params_init (&dh_params); - gnutls_dh_params_import_pkcs3 (dh_params, &p3, GNUTLS_X509_FMT_PEM); - gnutls_anon_set_server_dh_params (s_anoncred, dh_params); - gnutls_init (&server, GNUTLS_SERVER); - gnutls_priority_set_direct (server, "NONE:+VERS-TLS-ALL:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+ANON-DH", NULL); - gnutls_credentials_set (server, GNUTLS_CRD_ANON, s_anoncred); - gnutls_dh_set_prime_bits (server, 1024); - gnutls_transport_set_push_function (server, server_push); - gnutls_transport_set_pull_function (server, server_pull); - gnutls_transport_set_ptr (server, (gnutls_transport_ptr_t)server); - - gnutls_sbuf_init(&ssbuf, server, GNUTLS_SBUF_QUEUE_FLUSHES); - - gnutls_rnd(GNUTLS_RND_NONCE, server_buf, sizeof(server_buf)); - - /* Init client */ - gnutls_anon_allocate_client_credentials (&c_anoncred); - gnutls_init (&client, GNUTLS_CLIENT); - gnutls_priority_set_direct (client, "NONE:+VERS-TLS-ALL:+CIPHER-ALL:+MAC-ALL:+SIGN-ALL:+COMP-ALL:+ANON-DH", NULL); - gnutls_credentials_set (client, GNUTLS_CRD_ANON, c_anoncred); - gnutls_transport_set_push_function (client, client_push); - gnutls_transport_set_pull_function (client, client_pull); - gnutls_transport_set_ptr (client, (gnutls_transport_ptr_t)client); - - memset(client_buf, 0, sizeof(client_buf)); - - HANDSHAKE(client, server); - - if (debug) - success ("Handshake established\n"); - -#define SEND_SIZE 100 - left = sizeof(server_buf); - spos = 0; - cpos = 0; - while (left > 0) - { - if (left > SEND_SIZE) - { - ret = gnutls_sbuf_write(ssbuf, server_buf+spos, SEND_SIZE); - } - else - { - ret = gnutls_sbuf_write(ssbuf, server_buf+spos, left); - } - - if (ret >= 0) - { - left -= ret; - spos += ret; - ret = gnutls_sbuf_flush(ssbuf); - } - - if (ret < 0) - { - fail("Error sending %s\n", gnutls_strerror(ret)); - abort(); - } - - if (ret > 0) - { /* received in client side */ - ret = gnutls_record_recv(client, client_buf+cpos, sizeof(client_buf)-cpos); - if (ret > 0) - cpos += ret; - - if (ret < 0) - { - fail("Error receiving %s\n", gnutls_strerror(ret)); - abort(); - } - } - } - - if (memcmp(client_buf, server_buf, sizeof(server_buf)) != 0) - { - fail("Data do not match!\n"); - abort(); - } - - gnutls_record_send(client, LINE1, sizeof(LINE1)-1); - gnutls_record_send(client, LINE2, sizeof(LINE2)-1); - - ret = gnutls_sbuf_getline(ssbuf, &abuf, &abuf_size); - if (ret < 0) - { - fail("sbuf_getline error %s!\n", gnutls_strerror(ret)); - abort(); - } - - if (strcmp(abuf, LINE1) != 0) - { - fail("LINE1 Data do not match!\n"); - abort(); - } - - ret = gnutls_sbuf_getline(ssbuf, &abuf, &abuf_size); - if (ret < 0) - { - fail("sbuf_getline error %s!\n", gnutls_strerror(ret)); - abort(); - } - - if (strcmp(abuf, LINE2) != 0) - { - fail("LINE2 Data do not match!\n"); - abort(); - } - - gnutls_free(abuf); - gnutls_bye (client, GNUTLS_SHUT_RDWR); - gnutls_bye (server, GNUTLS_SHUT_RDWR); - - gnutls_sbuf_deinit (ssbuf); - gnutls_deinit (client); - gnutls_deinit (server); - - gnutls_anon_free_client_credentials (c_anoncred); - gnutls_anon_free_server_credentials (s_anoncred); - - gnutls_dh_params_deinit (dh_params); - - gnutls_global_deinit (); -} diff --git a/tests/mini-xssl.c b/tests/mini-xssl.c new file mode 100644 index 0000000000..e304e7aca9 --- /dev/null +++ b/tests/mini-xssl.c @@ -0,0 +1,406 @@ +/* + * Copyright (C) 2013 Nikos Mavrogiannopoulos + * + * 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 3 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 GnuTLS; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +/* Tests for the xssl interface */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <stdio.h> +#include <stdlib.h> + +#if defined(_WIN32) + +int main() +{ + exit(77); +} + +#else + +#include <string.h> +#include <sys/types.h> +#include <netinet/in.h> +#include <sys/socket.h> +#include <sys/wait.h> +#include <arpa/inet.h> +#include <unistd.h> +#include <gnutls/gnutls.h> +#include <gnutls/xssl.h> +#include <signal.h> + +#include "utils.h" + +#define TOFU_DB_FILE "tofu.tmp.db" + +static void terminate(void); + +/* This program tests the robustness of record + * decoding. + */ + +static time_t mytime (time_t * t) +{ + time_t then = 1359304177; + + if (t) + *t = then; + + return then; +} + + +static void +server_log_func (int level, const char *str) +{ +// fprintf (stderr, "server|<%d>| %s", level, str); +} + +static void +client_log_func (int level, const char *str) +{ + fprintf (stderr, "client|<%d>| %s", level, str); +} + +static unsigned char ca_pem[] = + "-----BEGIN CERTIFICATE-----\n" + "MIIDUDCCAgigAwIBAgIBADANBgkqhkiG9w0BAQsFADAZMRcwFQYDVQQDEw5HbnVU\n" + "TFMgVGVzdCBDQTAeFw0xMTA1MjgwODM2MzBaFw0zODEwMTIwODM2MzNaMBkxFzAV\n" + "BgNVBAMTDkdudVRMUyBUZXN0IENBMIIBUjANBgkqhkiG9w0BAQEFAAOCAT8AMIIB\n" + "OgKCATEAnORCsX1unl//fy2d1054XduIg/3CqVBaT3Hca65SEoDwh0KiPtQoOgZL\n" + "dKY2cobGs/ojYtOjcs0KnlPYdmtjEh6WEhuJU95v4TQdC4OLMiE56eIGq252hZAb\n" + "HoTL84Q14DxQWGuzQK830iml7fbw2WcIcRQ8vFGs8SzfXw63+MI6Fq6iMAQIqP08\n" + "WzGmRRzL5wvCiPhCVkrPmwbXoABub6AAsYwWPJB91M9/lx5gFH5k9/iPfi3s2Kg3\n" + "F8MOcppqFYjxDSnsfiz6eMh1+bYVIAo367vGVYHigXMEZC2FezlwIHaZzpEoFlY3\n" + "a7LFJ00yrjQ910r8UE+CEMTYzE40D0olCMo7FA9RCjeO3bUIoYaIdVTUGWEGHWSe\n" + "oxGei9Gkm6u+ASj8f+i0jxdD2qXsewIDAQABo0MwQTAPBgNVHRMBAf8EBTADAQH/\n" + "MA8GA1UdDwEB/wQFAwMHBgAwHQYDVR0OBBYEFE1Wt2oAWPFnkvSmdVUbjlMBA+/P\n" + "MA0GCSqGSIb3DQEBCwUAA4IBMQAesOgjGFi1zOYpA/N3gkUVRcBHDxmN7g2yOcqH\n" + "VfhFc+e4zhOehR11WCt2RgzNlnYVmV5zBmQBdTAt8Po/MVhLCDW1BULHlLvL0DFc\n" + "4sB1RlcGeQcCKQa4b+Q9VWf4f6TfuEWZQC5j5stiXjVgOqrOMrzKZ2eKWA4JsL9s\n" + "V+7ANSZE+hOt1X1mA8moyqe95U2Ecih+nFJSWSBd1WFiEzVnXv4FVWPXbH9HERDK\n" + "VbasjofWWmQO1YlQPishLgm1IbwqOkOk4sDgoLuUZ4GgP0DDeN6EmRDOzByrv+9u\n" + "f45Bl9IQf4IJNPLU9lEqjyMOydqT6kBi7fjV5ICuQZ4EeVJsOGuX7PqNyoDzJHLv\n" + "ferRfNLr6eQSHSxBhS0cVyDjb5gCawK6u7xTU+b7xikEie9k\n" + "-----END CERTIFICATE-----\n"; + +const gnutls_datum_t ca_cert = { ca_pem, + sizeof (ca_pem)-1 +}; + +static unsigned char server_cert_pem[] = + "-----BEGIN CERTIFICATE-----\n" + "MIICsDCCAWigAwIBAgIETeC0kjANBgkqhkiG9w0BAQsFADAZMRcwFQYDVQQDEw5H\n" + "bnVUTFMgVGVzdCBDQTAeFw0xMTA1MjgwODM4NDNaFw0zODEwMTIwODM4NDZaMDEx\n" + "LzAtBgNVBAMTJkdudVRMUyBUZXN0IHNlcnZlciAoRUNEU0EgY2VydGlmaWNhdGUp\n" + "ME4wEAYHKoZIzj0CAQYFK4EEACEDOgAE0vMmf/W0rRoUqBxH5Uq+c/sR76ElmyZM\n" + "e2zj3U9PRJ0maKstEOHkpaDaSU6s2Hyi9L88wS1ZX0ijgY0wgYowDAYDVR0TAQH/\n" + "BAIwADAUBgNVHREEDTALgglsb2NhbGhvc3QwEwYDVR0lBAwwCgYIKwYBBQUHAwEw\n" + "DwYDVR0PAQH/BAUDAweAADAdBgNVHQ4EFgQUJ97Q83IFpLgqeOnT1rX/JzCvlTQw\n" + "HwYDVR0jBBgwFoAUTVa3agBY8WeS9KZ1VRuOUwED788wDQYJKoZIhvcNAQELBQAD\n" + "ggExAErP9z8CCwt7YwA+SHoulNjqcXsngeKAKN9fVgV/XuspG6L2nU1WZvCjjFj6\n" + "jggMbJSElyCuLZJKlTC/DihXUgRXyswOzg9qQ7dDv+V/Qi95XH5slXNzYxMQSdoA\n" + "IaULVVDZcMFMVSc+TyAchJ6XwUY9umiysz3lSOioMQCch4MA366ZNqqnq5OD4moH\n" + "1SUX8CbRjA6SLpvffexLTB2Af+mFi8ReTkXCwB1LGEH1HRp/XzBc+/F9mavy3g/6\n" + "Hnjf2E1h2GDYXcJCVfE+ArjNS+R94jJwRMFBvwD/x2hsvpSajDpO0+GIxlGGKdyh\n" + "7o4puz/BqHwSzX9h7I7RvFEogDUNUzLgHMdcjq5usnmQpdWNUP8Xs/WqLjML+/PT\n" + "+jyCwmll0lPlC2RqAx3pM1XrjjQ=\n" + "-----END CERTIFICATE-----\n"; + +const gnutls_datum_t server_cert = { server_cert_pem, + sizeof (server_cert_pem)-1 +}; + +static unsigned char server_key_pem[] = + "-----BEGIN EC PRIVATE KEY-----\n" + "MGgCAQEEHHX3xeBOGgIxxtuhhpbwdwZnJztR7+uZTHnYuL+gBwYFK4EEACGhPAM6\n" + "AATS8yZ/9bStGhSoHEflSr5z+xHvoSWbJkx7bOPdT09EnSZoqy0Q4eSloNpJTqzY\n" + "fKL0vzzBLVlfSA==\n" + "-----END EC PRIVATE KEY-----\n"; + +const gnutls_datum_t server_key = { server_key_pem, + sizeof (server_key_pem)-1 +}; + +#define LINE1 "hello there people\n" +#define LINE2 "how are you doing today, all well?\n" + +static const char* test = NULL; + +#define err_quit(r) {fail("%s: Error in line %d: %s\n", test, __LINE__, gnutls_strerror(r)); exit(1);} + +static void +client (int fd, unsigned int vmethod, unsigned use_cert) +{ + int ret; + char *line = NULL; + size_t line_len; + xssl_cred_t cred; + xssl_t sb; + gnutls_cinput_st aux[2]; + unsigned int status; + unsigned aux_size = 0; + + gnutls_global_init (); + gnutls_global_set_time_function (mytime); + + if (debug) + { + gnutls_global_set_log_function (client_log_func); + gnutls_global_set_log_level (7); + } + + if (vmethod & GNUTLS_VMETHOD_GIVEN_CAS) + { + aux[aux_size].type = GNUTLS_CINPUT_TYPE_MEM; + aux[aux_size].contents = GNUTLS_CINPUT_CAS; + aux[aux_size].fmt = GNUTLS_X509_FMT_PEM; + aux[aux_size].i1.mem = ca_cert; + aux_size++; + } + + if (use_cert != 0) + { + aux[aux_size].type = GNUTLS_CINPUT_TYPE_MEM; + aux[aux_size].contents = GNUTLS_CINPUT_KEYPAIR; + aux[aux_size].fmt = GNUTLS_X509_FMT_PEM; + aux[aux_size].i1.mem = server_cert; + aux[aux_size].i2.mem = server_key; + aux_size++; + } + + if (vmethod & GNUTLS_VMETHOD_TOFU) + { + aux[aux_size].type = GNUTLS_CINPUT_TYPE_FILE; + aux[aux_size].contents = GNUTLS_CINPUT_TOFU_DB; + aux[aux_size].i1.file = TOFU_DB_FILE; + aux_size++; + } + + ret = xssl_cred_init(&cred, vmethod, aux, aux_size); + if (ret < 0) + err_quit(ret); + + /* Initialize TLS session + */ + ret = xssl_client_init(&sb, "localhost", NULL, (gnutls_transport_ptr_t)fd, + NULL, cred, &status, 0); + if (ret < 0) + { + if (ret == GNUTLS_E_AUTH_ERROR) + { + gnutls_datum_t txt; + + gnutls_certificate_verification_status_print(status, GNUTLS_CRT_X509, + &txt, 0); + + fprintf(stderr, "auth[%x]: %s\n", status, txt.data); + gnutls_free(txt.data); + } + err_quit(ret); + } + + ret = xssl_getline(sb, &line, &line_len); + if (ret < 0) + err_quit(ret); + + if (strcmp(line, LINE1) != 0) + { + fail("Error comparing first line\n"); + exit(1); + } + + ret = xssl_getline(sb, &line, &line_len); + if (ret < 0) + err_quit(ret); + + if (strcmp(line, LINE2) != 0) + { + fail("Error comparing first line\n"); + exit(1); + } + + gnutls_free(line); + + xssl_deinit(sb); + + close (fd); + + xssl_cred_deinit (cred); + + gnutls_global_deinit (); +} + + +/* These are global */ +pid_t child; + +static void terminate(void) +{ + kill(child, SIGTERM); + exit(1); +} + +static void +server (int fd, unsigned vmethod) +{ + int ret; + xssl_cred_t cred; + xssl_t sb; + gnutls_cinput_st aux[2]; + unsigned aux_size = 0; + + gnutls_global_init (); + + if (debug) + { + gnutls_global_set_log_function (client_log_func); + gnutls_global_set_log_level (7); + } + + + aux[aux_size].type = GNUTLS_CINPUT_TYPE_MEM; + aux[aux_size].contents = GNUTLS_CINPUT_KEYPAIR; + aux[aux_size].fmt = GNUTLS_X509_FMT_PEM; + aux[aux_size].i1.mem = server_cert; + aux[aux_size].i2.mem = server_key; + aux_size++; + + if (vmethod & GNUTLS_VMETHOD_GIVEN_CAS) + { + aux[aux_size].type = GNUTLS_CINPUT_TYPE_MEM; + aux[aux_size].contents = GNUTLS_CINPUT_CAS; + aux[aux_size].fmt = GNUTLS_X509_FMT_PEM; + aux[aux_size].i1.mem = ca_cert; + aux_size++; + } + + ret = xssl_cred_init(&cred, vmethod, aux, aux_size); + if (ret < 0) + err_quit(ret); + + /* Initialize TLS session + */ + ret = xssl_server_init(&sb, (gnutls_transport_ptr_t)fd, + NULL, cred, NULL, 0); + if (ret < 0) + err_quit(ret); + + ret = xssl_write(sb, LINE1, sizeof(LINE1)-1); + if (ret < 0) + err_quit(ret); + + ret = xssl_write(sb, LINE2, sizeof(LINE2)-1); + if (ret < 0) + err_quit(ret); + + ret = xssl_flush(sb); + if (ret < 0) + err_quit(ret); + + xssl_deinit(sb); + + close (fd); + + xssl_cred_deinit (cred); + + gnutls_global_deinit (); + +} + +static void start (unsigned vc, unsigned vs, unsigned ccert) +{ + int fd[2]; + int ret; + + ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fd); + if (ret < 0) + { + perror("socketpair"); + exit(1); + } + + child = fork (); + if (child < 0) + { + perror ("fork"); + fail ("fork"); + exit(1); + } + + if (child) + { + /* parent */ + close(fd[1]); + server (fd[0], vs); + waitpid(-1, NULL, 0); + //kill(child, SIGTERM); + } + else + { + close(fd[0]); + client (fd[1], vc, ccert); + exit(0); + } +} + +static void ch_handler(int sig) +{ +int status = 0; + + waitpid(-1, &status, 0); + if (WEXITSTATUS(status) != 0 || + (WIFSIGNALED(status) && WTERMSIG(status) == SIGSEGV)) + { + if (WIFSIGNALED(status)) + fail("Child died with sigsegv\n"); + else + fail("Child died with status %d\n", WEXITSTATUS(status)); + terminate(); + } + return; +} + +void +doit (void) +{ + signal(SIGCHLD, ch_handler); + + test = "test1: no auth"; + start(GNUTLS_VMETHOD_NO_AUTH, GNUTLS_VMETHOD_NO_AUTH, 0); + + test = "test2: server auth"; + start(GNUTLS_VMETHOD_GIVEN_CAS, GNUTLS_VMETHOD_NO_AUTH, 0); + + test = "test3: mutual auth"; + start(GNUTLS_VMETHOD_GIVEN_CAS, GNUTLS_VMETHOD_GIVEN_CAS, 1); + + remove(TOFU_DB_FILE); + test = "test4: trust on first use p1"; + start(GNUTLS_VMETHOD_TOFU, GNUTLS_VMETHOD_NO_AUTH, 0); + + test = "test5: trust on first use p2"; + start(GNUTLS_VMETHOD_TOFU, GNUTLS_VMETHOD_NO_AUTH, 0); + remove(TOFU_DB_FILE); + +} + +#endif /* _WIN32 */ |