diff options
author | Simon Josefsson <simon@josefsson.org> | 2007-10-08 11:38:26 +0200 |
---|---|---|
committer | Simon Josefsson <simon@josefsson.org> | 2007-10-08 11:38:26 +0200 |
commit | 1b07f0e8cfb9c72513c5e74d357846a4453af947 (patch) | |
tree | 1885da37a2c7549091f11f0f9cfcc70afd2bcbbb /lib | |
parent | ff08fecaebf983e5a66882734d4f71a714685b06 (diff) | |
parent | 1f24725c9a0b09e7a42ee18f2bb4c0fbac581b8f (diff) | |
download | gnutls-1b07f0e8cfb9c72513c5e74d357846a4453af947.tar.gz |
Merge branch 'master' of ssh://git.sv.gnu.org/srv/git/gnutls
Conflicts:
NEWS
Diffstat (limited to 'lib')
-rw-r--r-- | lib/auth_srp.c | 3 | ||||
-rw-r--r-- | lib/ext_srp.c | 23 | ||||
-rw-r--r-- | lib/gnutls_alert.c | 14 | ||||
-rw-r--r-- | lib/gnutls_errors.h | 1 | ||||
-rw-r--r-- | lib/gnutls_extensions.c | 4 | ||||
-rw-r--r-- | lib/gnutls_handshake.c | 96 | ||||
-rw-r--r-- | lib/gnutls_int.h | 9 | ||||
-rw-r--r-- | lib/gnutls_srp.c | 12 | ||||
-rw-r--r-- | lib/gnutls_state.c | 25 | ||||
-rw-r--r-- | lib/x509/Makefile.am | 2 | ||||
-rw-r--r-- | lib/x509/common.c | 4 | ||||
-rw-r--r-- | lib/x509/dn.c | 5 | ||||
-rw-r--r-- | lib/x509/xml.c | 762 |
13 files changed, 93 insertions, 867 deletions
diff --git a/lib/auth_srp.c b/lib/auth_srp.c index e30c069caa..d647020467 100644 --- a/lib/auth_srp.c +++ b/lib/auth_srp.c @@ -171,7 +171,8 @@ _gnutls_gen_srp_server_kx (gnutls_session_t session, opaque ** data) } /* copy from pwd_entry to local variables (actually in session) */ - if (_gnutls_mpi_scan_nz (&G, pwd_entry->g.data, &pwd_entry->g.size) < 0) + tmp_size = pwd_entry->g.size; + if (_gnutls_mpi_scan_nz (&G, pwd_entry->g.data, &tmp_size) < 0) { gnutls_assert (); return GNUTLS_E_MPI_SCAN_FAILED; diff --git a/lib/ext_srp.c b/lib/ext_srp.c index e8bd84e0c1..6350525679 100644 --- a/lib/ext_srp.c +++ b/lib/ext_srp.c @@ -40,15 +40,6 @@ _gnutls_srp_recv_params (gnutls_session_t session, const opaque * data, uint8_t len; ssize_t data_size = _data_size; - if (_gnutls_kx_priority (session, GNUTLS_KX_SRP) < 0 && - _gnutls_kx_priority (session, GNUTLS_KX_SRP_DSS) < 0 && - _gnutls_kx_priority (session, GNUTLS_KX_SRP_RSA) < 0) - { - /* algorithm was not allowed in this session - */ - return 0; - } - if (session->security_parameters.entity == GNUTLS_SERVER) { if (data_size > 0) @@ -117,19 +108,11 @@ _gnutls_srp_send_params (gnutls_session_t session, opaque * data, */ char *username = NULL, *password = NULL; - if (cred->get_function (session, - session->internals.handshake_restarted, - &username, &password) < 0 + if (cred->get_function (session, &username, &password) < 0 || username == NULL || password == NULL) { - - if (session->internals.handshake_restarted) - { - gnutls_assert (); - return GNUTLS_E_ILLEGAL_SRP_USERNAME; - } - - return 0; + gnutls_assert (); + return GNUTLS_E_ILLEGAL_SRP_USERNAME; } len = MIN (strlen (username), 255); diff --git a/lib/gnutls_alert.c b/lib/gnutls_alert.c index 92431bc799..be2843e1b3 100644 --- a/lib/gnutls_alert.c +++ b/lib/gnutls_alert.c @@ -62,8 +62,7 @@ static const gnutls_alert_entry sup_alerts[] = { {GNUTLS_A_UNSUPPORTED_EXTENSION, "An unsupported extension was sent"}, {GNUTLS_A_UNRECOGNIZED_NAME, "The server name sent was not recognized"}, - {GNUTLS_A_UNKNOWN_SRP_USERNAME, "The SRP username is not known"}, - {GNUTLS_A_MISSING_SRP_USERNAME, "The SRP username was not sent"}, + {GNUTLS_A_UNKNOWN_PSK_IDENTITY, "The SRP/PSK username is missing or not known"}, {GNUTLS_A_INNER_APPLICATION_FAILURE, "Inner application negotiation failed"}, {GNUTLS_A_INNER_APPLICATION_VERIFICATION, @@ -148,15 +147,14 @@ gnutls_alert_send (gnutls_session_t session, gnutls_alert_level_t level, * alert should be sent to the peer indicating that no renegotiation will * be performed. * - * If the return value is GNUTLS_E_INVALID_REQUEST, then there was no - * mapping to an alert. + * If there is no mapping to a valid alert the alert to indicate internal error + * is returned. * **/ int gnutls_error_to_alert (int err, int *level) { - int ret = GNUTLS_E_INVALID_REQUEST; - int _level = -1; + int ret, _level = -1; switch (err) { /* send appropriate alert */ @@ -241,6 +239,10 @@ gnutls_error_to_alert (int err, int *level) ret = GNUTLS_A_INSUFFICIENT_SECURITY; _level = GNUTLS_AL_FATAL; break; + default: + ret = GNUTLS_A_INTERNAL_ERROR; + _level = GNUTLS_AL_FATAL; + break; } if (level != NULL) diff --git a/lib/gnutls_errors.h b/lib/gnutls_errors.h index 46724708b0..4d98fa0a8c 100644 --- a/lib/gnutls_errors.h +++ b/lib/gnutls_errors.h @@ -25,7 +25,6 @@ #include <defines.h> #define GNUTLS_E_INT_RET_0 -1251 -#define GNUTLS_E_INT_HANDSHAKE_AGAIN -1252 #ifdef __FILE__ # ifdef __LINE__ diff --git a/lib/gnutls_extensions.c b/lib/gnutls_extensions.c index 20b1bbd414..4c54cbfb70 100644 --- a/lib/gnutls_extensions.c +++ b/lib/gnutls_extensions.c @@ -177,8 +177,8 @@ _gnutls_parse_extensions (gnutls_session_t session, const opaque * data, type = _gnutls_read_uint16 (&data[pos]); pos += 2; - _gnutls_debug_log ("EXT[%x]: Received extension '%s'\n", session, - _gnutls_extension_get_name (type)); + _gnutls_debug_log ("EXT[%x]: Received extension '%s/%d'\n", session, + _gnutls_extension_get_name (type),type); if ((ret = _gnutls_extension_list_check (session, type)) < 0) { diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c index f8d2724ff3..753bfe2d14 100644 --- a/lib/gnutls_handshake.c +++ b/lib/gnutls_handshake.c @@ -282,12 +282,12 @@ int _gnutls_read_client_hello (gnutls_session_t session, opaque * data, int datalen) { - uint8_t session_id_len, z; + uint8_t session_id_len; int pos = 0, ret; - uint16_t suite_size; + uint16_t suite_size, comp_size; gnutls_protocol_t version; int len = datalen; - opaque rnd[TLS_RANDOM_SIZE], *suite_ptr; + opaque rnd[TLS_RANDOM_SIZE], *suite_ptr, *comp_ptr; gnutls_protocol_t ver; if (session->internals.v2_hello != 0) @@ -376,20 +376,14 @@ _gnutls_read_client_hello (gnutls_session_t session, opaque * data, suite_ptr = &data[pos]; pos += suite_size; - /* Select an appropriate compression method + /* Point to the compression methods */ DECR_LEN (len, 1); - z = data[pos++]; /* z is the number of compression methods */ + comp_size = data[pos++]; /* z is the number of compression methods */ - DECR_LEN (len, z); - ret = _gnutls_server_select_comp_method (session, &data[pos], z); - pos += z; - - if (ret < 0) - { - gnutls_assert (); - return ret; - } + DECR_LEN (len, comp_size); + comp_ptr = &data[pos]; + pos += comp_size; /* Parse the extensions (if any) */ @@ -403,6 +397,16 @@ _gnutls_read_client_hello (gnutls_session_t session, opaque * data, } } + if (session->internals.user_hello_func != NULL) + { + ret = session->internals.user_hello_func( session); + if (ret < 0) + { + gnutls_assert(); + return ret; + } + } + /* select an appropriate cipher suite */ ret = _gnutls_server_select_suite (session, suite_ptr, suite_size); @@ -412,6 +416,14 @@ _gnutls_read_client_hello (gnutls_session_t session, opaque * data, return ret; } + /* select appropriate compression method */ + ret = _gnutls_server_select_comp_method (session, comp_ptr, comp_size); + if (ret < 0) + { + gnutls_assert (); + return ret; + } + return 0; } @@ -1115,17 +1127,6 @@ _gnutls_recv_handshake (gnutls_session_t session, uint8_t ** data, if (ret < 0) { - /* In SRP when expecting the server hello we may receive - * an alert instead. Do as the draft demands. - */ - if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED && - gnutls_alert_get (session) == GNUTLS_A_MISSING_SRP_USERNAME && - type == GNUTLS_HANDSHAKE_SERVER_HELLO) - { - gnutls_assert (); - return GNUTLS_E_INT_HANDSHAKE_AGAIN; - } - if (ret == GNUTLS_E_UNEXPECTED_HANDSHAKE_PACKET && optional == OPTIONAL_PACKET) { @@ -1839,19 +1840,19 @@ _gnutls_send_server_hello (gnutls_session_t session, int again) session->security_parameters.extensions.srp_username[0] == 0) { /* The peer didn't send a valid SRP extension with the - * SRP username. The draft requires that we send an - * alert and start the handshake again. + * SRP username. The draft requires that we send a fatal + * alert and abort. */ gnutls_assert (); - ret = gnutls_alert_send (session, GNUTLS_AL_WARNING, - GNUTLS_A_MISSING_SRP_USERNAME); + ret = gnutls_alert_send (session, GNUTLS_AL_FATAL, + GNUTLS_A_UNKNOWN_PSK_IDENTITY); if (ret < 0) { gnutls_assert (); return ret; } - return GNUTLS_E_INT_HANDSHAKE_AGAIN; + return GNUTLS_E_ILLEGAL_SRP_USERNAME; } } #endif @@ -2217,21 +2218,8 @@ gnutls_handshake (gnutls_session_t session) return 0; } -/* Here if GNUTLS_E_INT_HANDSHAKE_AGAIN is received we go to - * restart. This works because this error code may only be - * received on the first 2 handshake packets. If for some reason - * this changes we should return GNUTLS_E_AGAIN. - */ #define IMED_RET( str, ret) do { \ if (ret < 0) { \ - if (ret == GNUTLS_E_INT_HANDSHAKE_AGAIN && \ - session->internals.handshake_restarted == 1) \ - ret = GNUTLS_E_INTERNAL_ERROR; \ - if (ret == GNUTLS_E_INT_HANDSHAKE_AGAIN) { \ - STATE = STATE0; \ - session->internals.handshake_restarted = 1; \ - goto restart; \ - } \ if (gnutls_error_is_fatal(ret)==0) return ret; \ gnutls_assert(); \ ERR( str, ret); \ @@ -2263,7 +2251,6 @@ _gnutls_handshake_client (gnutls_session_t session) session_id_size, buf, sizeof (buf))); #endif -restart: switch (STATE) { @@ -2491,8 +2478,6 @@ _gnutls_handshake_server (gnutls_session_t session) { int ret = 0; -restart: - switch (STATE) { case STATE0: @@ -2594,8 +2579,6 @@ _gnutls_handshake_common (gnutls_session_t session) { int ret = 0; -restart: - /* send and recv the change cipher spec and finished messages */ if ((session->internals.resumed == RESUME_TRUE && session->security_parameters.entity == GNUTLS_CLIENT) @@ -2801,11 +2784,11 @@ _gnutls_remove_unwanted_ciphersuites (gnutls_session_t session, int ret = 0; cipher_suite_st *newSuite, cs; int newSuiteSize = 0, i; - gnutls_certificate_credentials_t x509_cred; + gnutls_certificate_credentials_t cert_cred; gnutls_kx_algorithm_t kx; int server = session->security_parameters.entity == GNUTLS_SERVER ? 1 : 0; - gnutls_kx_algorithm_t *alg; - int alg_size; + gnutls_kx_algorithm_t *alg = NULL; + int alg_size = 0; /* if we should use a specific certificate, * we should remove all algorithms that are not supported @@ -2813,22 +2796,23 @@ _gnutls_remove_unwanted_ciphersuites (gnutls_session_t session, * method (CERTIFICATE). */ - x509_cred = + cert_cred = (gnutls_certificate_credentials_t) _gnutls_get_cred (session->key, GNUTLS_CRD_CERTIFICATE, NULL); - /* if x509_cred==NULL we should remove all X509 ciphersuites + /* If there are certificate credentials, find an appropriate certificate + * or disable them; */ - if (session->security_parameters.entity == GNUTLS_SERVER - && x509_cred != NULL) + && cert_cred != NULL) { ret = _gnutls_server_select_cert (session, requested_pk_algo); if (ret < 0) { gnutls_assert (); - return ret; + _gnutls_x509_log("Could not find an appropriate certificate: %s\n", gnutls_strerror(ret)); + cert_cred = NULL; } } diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index 1c9f10e5f5..2cff4d1eda 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -549,6 +549,10 @@ typedef struct gnutls_db_retr_func db_retrieve_func; gnutls_db_remove_func db_remove_func; void *db_ptr; + + /* post client hello callback (server side only) + */ + gnutls_handshake_post_client_hello_func user_hello_func; /* Holds the record size requested by the * user. @@ -612,11 +616,6 @@ typedef struct char *srp_username; char *srp_password; - /* This is only set in SRP, when the handshake is - * restarted if an username is not found. - */ - int handshake_restarted; - /* Here we cache the DH or RSA parameters got from the * credentials structure, or from a callback. That is to * minimize external calls. diff --git a/lib/gnutls_srp.c b/lib/gnutls_srp.c index 7a54d2d382..99678a7035 100644 --- a/lib/gnutls_srp.c +++ b/lib/gnutls_srp.c @@ -612,21 +612,15 @@ gnutls_srp_set_server_credentials_function (gnutls_srp_server_credentials_t * This function can be used to set a callback to retrieve the username and * password for client SRP authentication. * The callback's function form is: - * int (*callback)(gnutls_session_t, unsigned int times, char** username, + * int (*callback)(gnutls_session_t, char** username, * char** password); * * The @username and @password must be allocated using gnutls_malloc(). - * @times will be 0 the first time called, and 1 the second. * @username and @password should be ASCII strings or UTF-8 strings * prepared using the "SASLprep" profile of "stringprep". * - * The callback function will be called once or twice per handshake. - * The first time called, is before the ciphersuite is negotiated. - * At that time if the callback returns a negative error code, - * the callback will be called again if SRP has been - * negotiated. This uses a special TLS-SRP idiom in order to avoid - * asking the user for SRP password and username if the server does - * not support SRP. + * The callback function will be called once per handshake before the + * initial hello message is sent. * * The callback should not return a negative error code the second * time called, since the handshake procedure will be aborted. diff --git a/lib/gnutls_state.c b/lib/gnutls_state.c index 7e07e6773d..4bbbbace46 100644 --- a/lib/gnutls_state.c +++ b/lib/gnutls_state.c @@ -209,8 +209,6 @@ _gnutls_handshake_internal_state_clear (gnutls_session_t session) session->internals.last_handshake_in = -1; session->internals.last_handshake_out = -1; - session->internals.handshake_restarted = 0; - session->internals.resumable = RESUME_TRUE; _gnutls_free_datum (&session->internals.recv_buffer); @@ -1209,3 +1207,26 @@ _gnutls_rsa_pms_set_version (gnutls_session_t session, session->internals.rsa_pms_version[0] = major; session->internals.rsa_pms_version[1] = minor; } + +/** + * gnutls_handshake_set_post_client_hello_function - This function will a callback to be called after the client hello is received + * @res: is a gnutls_anon_server_credentials_t structure + * @func: is the function to be called + * + * This function will set a callback to be called after the client hello + * has been received (callback valid in server side only). This allows the + * server to adjust settings based on received extensions. + * + * Those settings could be ciphersuites, requesting certificate, or anything + * else except for version negotiation (this is done before the hello message + * is parsed). + * + * This callback must return 0 on success or a gnutls error code to + * terminate the handshake. + * + **/ +void gnutls_handshake_set_post_client_hello_function( gnutls_session_t session, + gnutls_handshake_post_client_hello_func func) +{ + session->internals.user_hello_func = func; +} diff --git a/lib/x509/Makefile.am b/lib/x509/Makefile.am index 2cdc2f61a4..621066786f 100644 --- a/lib/x509/Makefile.am +++ b/lib/x509/Makefile.am @@ -30,7 +30,7 @@ noinst_LTLIBRARIES = libgnutls_x509.la libgnutls_x509_la_SOURCES = crl.c dn.c common.c x509.c extensions.c \ dsa.c rfc2818_hostname.c verify.c mpi.c privkey.c pkcs7.c \ - crq.c xml.c sign.c privkey_pkcs8.c pkcs12.c pkcs12_bag.c \ + crq.c sign.c privkey_pkcs8.c pkcs12.c pkcs12_bag.c \ pkcs12_encr.c x509_write.c crl_write.c dn.h common.h x509.h \ extensions.h pkcs7.h verify.h mpi.h crq.h sign.h privkey.h \ pkcs12.h rfc2818.h dsa.h output.c diff --git a/lib/x509/common.c b/lib/x509/common.c index e1b7f7a2d6..515dcfe8d0 100644 --- a/lib/x509/common.c +++ b/lib/x509/common.c @@ -183,6 +183,7 @@ _gnutls_x509_oid_data2string (const char *oid, void *value, const char *ANAME = NULL; int CHOICE = -1, len = -1, result; ASN1_TYPE tmpasn = ASN1_TYPE_EMPTY; + char asn1_err[MAX_ERROR_DESCRIPTION_SIZE] = ""; if (value == NULL || value_size <= 0 || res_size == NULL) { @@ -217,9 +218,10 @@ _gnutls_x509_oid_data2string (const char *oid, void *value, } if ((result = - asn1_der_decoding (&tmpasn, value, value_size, NULL)) != ASN1_SUCCESS) + asn1_der_decoding (&tmpasn, value, value_size, asn1_err)) != ASN1_SUCCESS) { gnutls_assert (); + _gnutls_x509_log("asn1_der_decoding: %s:%s\n", str, asn1_err); asn1_delete_structure (&tmpasn); return _gnutls_asn2err (result); } diff --git a/lib/x509/dn.c b/lib/x509/dn.c index d891763500..33927cdac2 100644 --- a/lib/x509/dn.c +++ b/lib/x509/dn.c @@ -261,12 +261,15 @@ _gnutls_x509_parse_dn (ASN1_TYPE asn1_struct, STR_APPEND (ldap_desc); STR_APPEND ("="); + result = 0; + if (printable) result = _gnutls_x509_oid_data2string (oid, value2, len, string, &sizeof_string); - else + + if (!printable || result < 0) result = _gnutls_x509_data2hex (value2, len, string, &sizeof_string); diff --git a/lib/x509/xml.c b/lib/x509/xml.c deleted file mode 100644 index d20f9ae42e..0000000000 --- a/lib/x509/xml.c +++ /dev/null @@ -1,762 +0,0 @@ -/* - * Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation - * - * Author: Nikos Mavroyanopoulos - * - * This file is part of GNUTLS. - * - * The GNUTLS library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public License - * as published by the Free Software Foundation; either version 2.1 of - * the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, - * USA - * - */ - - -/* This file has the required functions to convert an X.509 DER certificate - * to XML format. - */ - -#include <defines.h> - -#if 1 - -#include <gnutls_int.h> - -/* The function below rely on some internal libtasn1 functions. While - it would be easy to export them (or copy them) we prefer not to at - this point. If you need the XML functionality, simply build with - --with-included-libtasn1 and change the '1' above to '0', or help - us add XML export functions to libtasn1 proper. */ - -int -gnutls_x509_crt_to_xml (gnutls_x509_crt_t cert, gnutls_datum_t * res, - int detail) -{ - return GNUTLS_E_INTERNAL_ERROR; -} - -#else - -#ifdef ENABLE_PKI - -#include <int.h> -#include <errors.h> -#include <structure.h> -#include <parser_aux.h> -#include <gnutls_int.h> -#include <gnutls_datum.h> -#include <gnutls_global.h> -#include <gnutls_errors.h> -#include <gnutls_str.h> -#include <gnutls_x509.h> -#include <x509.h> -#include <common.h> - -static int _gnutls_x509_expand_extensions (ASN1_TYPE * rasn); - -static const void * -find_default_value (ASN1_TYPE x) -{ - ASN1_TYPE p = x; - - if (x->value == NULL && x->type & CONST_DEFAULT) - { - if (x->down) - { - x = x->down; - do - { - if (type_field (x->type) == TYPE_DEFAULT) - { - if (type_field (p->type) == TYPE_BOOLEAN) - { - if (x->type & CONST_TRUE) - return "TRUE"; - else - return "FALSE"; - } - else - return x->value; - } - x = x->right; - } - while (x != NULL); - - } - } - return NULL; -} - - -static int -is_node_printable (ASN1_TYPE x) -{ - switch (type_field (x->type)) - { - case TYPE_TAG: - case TYPE_SIZE: - case TYPE_DEFAULT: - return 0; - case TYPE_CONSTANT: - { - ASN1_TYPE up = _asn1_find_up (x); - - if (up != NULL && type_field (up->type) != TYPE_ANY && - up->value != NULL) - return 0; - } - return 1; - } - if (x->name == NULL && _asn1_find_up (x) != NULL) - return 0; - if (x->value == NULL && x->down == NULL) - return 0; - return 1; -} - -/* returns true if the node is the only one printable in - * the level down of it. - */ -static int -is_leaf (ASN1_TYPE p) -{ - ASN1_TYPE x; - - if (p == NULL) - return 1; - if (p->down == NULL) - return 1; - - x = p->down; - - while (x != NULL) - { - if (is_node_printable (x)) - return 0; - if (is_leaf (x) == 0) - return 0; - x = x->right; - } - - return 1; - -} - -#define APPEND(y, z) if (_gnutls_string_append_data( &str, y, z) < 0) { \ - _gnutls_string_clear( &str); \ - gnutls_assert(); \ - return GNUTLS_E_MEMORY_ERROR; \ - } -#define STR_APPEND(y) if (_gnutls_string_append_str( &str, y) < 0) { \ - _gnutls_string_clear( &str); \ - gnutls_assert(); \ - return GNUTLS_E_MEMORY_ERROR; \ - } - -#define UNNAMED "unnamed" -#define ROOT "certificate" -/* This function removes the '?' character from ASN.1 names - */ -static int -normalize_name (ASN1_TYPE p, char *output, int output_size) -{ - const char *name; - - if (output_size > 0) - output[0] = 0; - else - return GNUTLS_E_INTERNAL_ERROR; - - if (p == NULL) - return GNUTLS_E_INTERNAL_ERROR; - - name = p->name; - if (name == NULL) - name = ROOT; - - if (type_field (p->type) == TYPE_CONSTANT) - { - ASN1_TYPE up = _asn1_find_up (p); - const char *tmp; - - if (up && type_field (up->type) == TYPE_ANY && - up->left && up->left->value && - up->type & CONST_DEFINED_BY && - type_field (up->left->type) == TYPE_OBJECT_ID) - { - - tmp = - asn1_find_structure_from_oid (_gnutls_get_pkix (), - up->left->value); - if (tmp != NULL) - _gnutls_str_cpy (output, output_size, tmp); - else - { - _gnutls_str_cpy (output, output_size, "DEFINED_BY_"); - _gnutls_str_cat (output, output_size, name); - } - } - else - { - _gnutls_str_cpy (output, output_size, "DEFINED_BY_"); - _gnutls_str_cat (output, output_size, name); - } - - - return 0; - } - - if (name[0] == '?') - { - _gnutls_str_cpy (output, output_size, UNNAMED); - if (strlen (name) > 1) - _gnutls_str_cat (output, output_size, &name[1]); - } - else - { - _gnutls_str_cpy (output, output_size, name); - } - return 0; -} - -#define XML_HEADER "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n" \ - "<gnutls:x509:certificate version=\"1.1\">\n" - -#define XML_FOOTER "</gnutls:x509:certificate>\n" - -static int -_gnutls_asn1_get_structure_xml (ASN1_TYPE structure, - gnutls_datum_t * res, int detail) -{ - node_asn *p, *root; - int k, indent = 0, len, len2, len3; - opaque tmp[1024]; - char nname[256]; - int ret; - gnutls_string str; - - if (res == NULL || structure == NULL) - { - gnutls_assert (); - return GNUTLS_E_INVALID_REQUEST; - } - - _gnutls_string_init (&str, malloc, realloc, free); - - STR_APPEND (XML_HEADER); - indent = 1; - - root = _asn1_find_node (structure, ""); - - if (root == NULL) - { - gnutls_assert (); - _gnutls_string_clear (&str); - return GNUTLS_E_INTERNAL_ERROR; - } - - if (detail == GNUTLS_XML_SHOW_ALL) - ret = asn1_expand_any_defined_by (_gnutls_get_pkix (), &structure); - /* we don't need to check the error value - * here. - */ - - if (detail == GNUTLS_XML_SHOW_ALL) - { - ret = _gnutls_x509_expand_extensions (&structure); - if (ret < 0) - { - gnutls_assert (); - return ret; - } - } - - p = root; - while (p) - { - if (is_node_printable (p)) - { - for (k = 0; k < indent; k++) - APPEND (" ", 1); - - if ((ret = normalize_name (p, nname, sizeof (nname))) < 0) - { - _gnutls_string_clear (&str); - gnutls_assert (); - return ret; - } - - APPEND ("<", 1); - STR_APPEND (nname); - } - - if (is_node_printable (p)) - { - switch (type_field (p->type)) - { - case TYPE_DEFAULT: - STR_APPEND (" type=\"DEFAULT\""); - break; - case TYPE_NULL: - STR_APPEND (" type=\"NULL\""); - break; - case TYPE_IDENTIFIER: - STR_APPEND (" type=\"IDENTIFIER\""); - break; - case TYPE_INTEGER: - STR_APPEND (" type=\"INTEGER\""); - STR_APPEND (" encoding=\"HEX\""); - break; - case TYPE_ENUMERATED: - STR_APPEND (" type=\"ENUMERATED\""); - STR_APPEND (" encoding=\"HEX\""); - break; - case TYPE_TIME: - STR_APPEND (" type=\"TIME\""); - break; - case TYPE_BOOLEAN: - STR_APPEND (" type=\"BOOLEAN\""); - break; - case TYPE_SEQUENCE: - STR_APPEND (" type=\"SEQUENCE\""); - break; - case TYPE_BIT_STRING: - STR_APPEND (" type=\"BIT STRING\""); - STR_APPEND (" encoding=\"HEX\""); - break; - case TYPE_OCTET_STRING: - STR_APPEND (" type=\"OCTET STRING\""); - STR_APPEND (" encoding=\"HEX\""); - break; - case TYPE_SEQUENCE_OF: - STR_APPEND (" type=\"SEQUENCE OF\""); - break; - case TYPE_OBJECT_ID: - STR_APPEND (" type=\"OBJECT ID\""); - break; - case TYPE_ANY: - STR_APPEND (" type=\"ANY\""); - if (!p->down) - STR_APPEND (" encoding=\"HEX\""); - break; - case TYPE_CONSTANT: - { - ASN1_TYPE up = _asn1_find_up (p); - - if (up && type_field (up->type) == TYPE_ANY && - up->left && up->left->value && - up->type & CONST_DEFINED_BY && - type_field (up->left->type) == TYPE_OBJECT_ID) - { - - if (_gnutls_x509_oid_data_printable - (up->left->value) == 0) - { - STR_APPEND (" encoding=\"HEX\""); - } - - } - } - break; - case TYPE_SET: - STR_APPEND (" type=\"SET\""); - break; - case TYPE_SET_OF: - STR_APPEND (" type=\"SET OF\""); - break; - case TYPE_CHOICE: - STR_APPEND (" type=\"CHOICE\""); - break; - case TYPE_DEFINITIONS: - STR_APPEND (" type=\"DEFINITIONS\""); - break; - default: - break; - } - } - - - if (p->type == TYPE_BIT_STRING) - { - len2 = -1; - len = asn1_get_length_der (p->value, p->value_len, &len2); - snprintf (tmp, sizeof (tmp), " length=\"%i\"", - (len - 1) * 8 - (p->value[len2])); - STR_APPEND (tmp); - } - - if (is_node_printable (p)) - STR_APPEND (">"); - - if (is_node_printable (p)) - { - const unsigned char *value; - - if (p->value == NULL) - value = find_default_value (p); - else - value = p->value; - - switch (type_field (p->type)) - { - - case TYPE_DEFAULT: - if (value) - STR_APPEND (value); - break; - case TYPE_IDENTIFIER: - if (value) - STR_APPEND (value); - break; - case TYPE_INTEGER: - if (value) - { - len2 = -1; - len = asn1_get_length_der (value, p->value_len, &len2); - - for (k = 0; k < len; k++) - { - snprintf (tmp, sizeof (tmp), "%02X", (value)[k + len2]); - STR_APPEND (tmp); - } - - } - break; - case TYPE_ENUMERATED: - if (value) - { - len2 = -1; - len = asn1_get_length_der (value, p->value_len, &len2); - - for (k = 0; k < len; k++) - { - snprintf (tmp, sizeof (tmp), "%02X", (value)[k + len2]); - STR_APPEND (tmp); - } - } - break; - case TYPE_TIME: - if (value) - STR_APPEND (value); - break; - case TYPE_BOOLEAN: - if (value) - { - if (value[0] == 'T') - { - STR_APPEND ("TRUE"); - } - else if (value[0] == 'F') - { - STR_APPEND ("FALSE"); - } - } - break; - case TYPE_BIT_STRING: - if (value) - { - len2 = -1; - len = asn1_get_length_der (value, p->value_len, &len2); - - for (k = 1; k < len; k++) - { - snprintf (tmp, sizeof (tmp), "%02X", (value)[k + len2]); - STR_APPEND (tmp); - } - } - break; - case TYPE_OCTET_STRING: - if (value) - { - len2 = -1; - len = asn1_get_length_der (value, p->value_len, &len2); - for (k = 0; k < len; k++) - { - snprintf (tmp, sizeof (tmp), "%02X", (value)[k + len2]); - STR_APPEND (tmp); - } - } - break; - case TYPE_OBJECT_ID: - if (value) - STR_APPEND (value); - break; - case TYPE_ANY: - if (!p->down) - { - if (value) - { - len3 = -1; - len2 = asn1_get_length_der (value, p->value_len, &len3); - for (k = 0; k < len2; k++) - { - snprintf (tmp, sizeof (tmp), - "%02X", (value)[k + len3]); - STR_APPEND (tmp); - } - } - } - break; - case TYPE_CONSTANT: - { - ASN1_TYPE up = _asn1_find_up (p); - - if (up && type_field (up->type) == TYPE_ANY && - up->left && up->left->value && - up->type & CONST_DEFINED_BY && - type_field (up->left->type) == TYPE_OBJECT_ID) - { - - len2 = - asn1_get_length_der (up->value, up->value_len, &len3); - - if (len2 > 0 && strcmp (p->name, "type") == 0) - { - size_t tmp_len = sizeof (tmp); - ret = - _gnutls_x509_oid_data2string (up->left-> - value, - up->value + len3, - len2, tmp, &tmp_len); - - if (ret >= 0) - { - STR_APPEND (tmp); - } - } - else - { - for (k = 0; k < len2; k++) - { - snprintf (tmp, sizeof (tmp), - "%02X", (up->value)[k + len3]); - STR_APPEND (tmp); - } - - } - } - else - { - if (value) - STR_APPEND (value); - } - - } - break; - case TYPE_SET: - case TYPE_SET_OF: - case TYPE_CHOICE: - case TYPE_DEFINITIONS: - case TYPE_SEQUENCE_OF: - case TYPE_SEQUENCE: - case TYPE_NULL: - break; - default: - break; - } - } - - if (p->down && is_node_printable (p)) - { - ASN1_TYPE x; - p = p->down; - indent += 2; - x = p; - do - { - if (is_node_printable (x)) - { - STR_APPEND ("\n"); - break; - } - x = x->right; - } - while (x != NULL); - } - else if (p == root) - { - if (is_node_printable (p)) - { - if ((ret = normalize_name (p, nname, sizeof (nname))) < 0) - { - _gnutls_string_clear (&str); - gnutls_assert (); - return ret; - } - - APPEND ("</", 2); - STR_APPEND (nname); - APPEND (">\n", 2); - } - p = NULL; - break; - } - else - { - if (is_node_printable (p)) - { - if ((ret = normalize_name (p, nname, sizeof (nname))) < 0) - { - _gnutls_string_clear (&str); - gnutls_assert (); - return ret; - } - - APPEND ("</", 2); - STR_APPEND (nname); - APPEND (">\n", 2); - } - if (p->right) - p = p->right; - else - { - while (1) - { - ASN1_TYPE old_p; - - old_p = p; - - p = _asn1_find_up (p); - indent -= 2; - if (is_node_printable (p)) - { - if (!is_leaf (p)) /* XXX */ - for (k = 0; k < indent; k++) - STR_APPEND (" "); - - if ((ret = - normalize_name (p, nname, sizeof (nname))) < 0) - { - _gnutls_string_clear (&str); - gnutls_assert (); - return ret; - } - - APPEND ("</", 2); - STR_APPEND (nname); - APPEND (">\n", 2); - } - if (p == root) - { - p = NULL; - break; - } - - if (p->right) - { - p = p->right; - break; - } - } - } - } - } - - STR_APPEND (XML_FOOTER); - APPEND ("\n\0", 2); - - *res = _gnutls_string2datum (&str); - res->size -= 1; /* null is not included in size */ - - return 0; -} - -/** - * gnutls_x509_crt_to_xml - This function parses an RDN sequence - * @cert: should contain a gnutls_x509_crt_t structure - * @res: The datum that will hold the result - * @detail: The detail level (must be GNUTLS_XML_SHOW_ALL or GNUTLS_XML_NORMAL) - * - * This function will return the XML structures of the given X.509 - * certificate. The XML structures are allocated internally (with - * malloc) and stored into res. - * - * Returns a negative error code in case of an error. - * - * Deprecated: This function is currently not implemented. See the - * NEWS entry for GnuTLS version 1.3.5. - * - **/ -int -gnutls_x509_crt_to_xml (gnutls_x509_crt_t cert, gnutls_datum_t * res, - int detail) -{ - int result; - - res->data = NULL; - res->size = 0; - - result = _gnutls_asn1_get_structure_xml (cert->cert, res, detail); - if (result < 0) - { - gnutls_assert (); - return result; - } - - return 0; -} - -/* This function will attempt to parse Extensions in - * an X509v3 certificate - * - * If no_critical_ext is non zero, then unsupported critical extensions - * do not lead into a fatal error. - */ -static int -_gnutls_x509_expand_extensions (ASN1_TYPE * rasn) -{ - int k, result, len; - char name[128], name2[128], counter[MAX_INT_DIGITS]; - char name1[128]; - char extnID[128]; - - k = 0; - do - { - k++; - - _gnutls_str_cpy (name, sizeof (name), "tbsCertificate.extensions.?"); - _gnutls_int2str (k, counter); - _gnutls_str_cat (name, sizeof (name), counter); - - _gnutls_str_cpy (name2, sizeof (name2), name); - _gnutls_str_cat (name2, sizeof (name2), ".extnID"); - - _gnutls_str_cpy (name1, sizeof (name1), name); - _gnutls_str_cat (name1, sizeof (name1), ".extnValue"); - - len = sizeof (extnID) - 1; - - result = asn1_expand_octet_string (_gnutls_get_pkix (), - rasn, name1, name2); - - if (result == ASN1_ELEMENT_NOT_FOUND) - break; - else if (result != ASN1_SUCCESS) - { - gnutls_assert (); - return _gnutls_asn2err (result); - } - - } - while (1); - - if (result == ASN1_ELEMENT_NOT_FOUND) - return 0; - else - return _gnutls_asn2err (result); -} - -#endif -#endif |