summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/auth_srp.c3
-rw-r--r--lib/ext_srp.c23
-rw-r--r--lib/gnutls_alert.c14
-rw-r--r--lib/gnutls_errors.h1
-rw-r--r--lib/gnutls_extensions.c4
-rw-r--r--lib/gnutls_handshake.c96
-rw-r--r--lib/gnutls_int.h9
-rw-r--r--lib/gnutls_srp.c12
-rw-r--r--lib/gnutls_state.c25
-rw-r--r--lib/x509/Makefile.am2
-rw-r--r--lib/x509/common.c4
-rw-r--r--lib/x509/dn.c5
-rw-r--r--lib/x509/xml.c762
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