summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.am2
-rw-r--r--lib/includes/gnutls/gnutls.h.in24
-rw-r--r--lib/libgnutls.map2
-rw-r--r--lib/openpgp/output.c7
-rw-r--r--lib/system.c76
-rw-r--r--lib/system.h2
-rw-r--r--lib/verify-ssh.c489
-rw-r--r--lib/x509/output.c16
8 files changed, 611 insertions, 7 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index d692a5864f..820f09062d 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -74,7 +74,7 @@ COBJECTS = gnutls_record.c gnutls_compress.c debug.c gnutls_cipher.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 hash.c gnutls_dtls.c system_override.c \
- crypto-backend.c
+ crypto-backend.c verify-ssh.c
if ENABLE_PKCS11
COBJECTS += pkcs11.c pkcs11_privkey.c pkcs11_write.c pkcs11_secret.c
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
index 45008ae8d5..415e282719 100644
--- a/lib/includes/gnutls/gnutls.h.in
+++ b/lib/includes/gnutls/gnutls.h.in
@@ -526,6 +526,7 @@ extern "C"
* @GNUTLS_CRT_UNKNOWN: Unknown certificate type.
* @GNUTLS_CRT_X509: X.509 Certificate.
* @GNUTLS_CRT_OPENPGP: OpenPGP certificate.
+ * @GNUTLS_CRT_RAW: Raw public key (SubjectPublicKey)
*
* Enumeration of different certificate types.
*/
@@ -533,7 +534,8 @@ extern "C"
{
GNUTLS_CRT_UNKNOWN = 0,
GNUTLS_CRT_X509 = 1,
- GNUTLS_CRT_OPENPGP = 2
+ GNUTLS_CRT_OPENPGP = 2,
+ GNUTLS_CRT_RAW = 3
} gnutls_certificate_type_t;
/**
@@ -552,6 +554,7 @@ extern "C"
/**
* gnutls_certificate_print_formats_t:
* @GNUTLS_CRT_PRINT_FULL: Full information about certificate.
+ * @GNUTLS_CRT_PRINT_COMPACT: Information about certificate name in one line, plus identification of the public key.
* @GNUTLS_CRT_PRINT_ONELINE: Information about certificate in one line.
* @GNUTLS_CRT_PRINT_UNSIGNED_FULL: All info for an unsigned certificate.
*
@@ -561,7 +564,8 @@ extern "C"
{
GNUTLS_CRT_PRINT_FULL = 0,
GNUTLS_CRT_PRINT_ONELINE = 1,
- GNUTLS_CRT_PRINT_UNSIGNED_FULL = 2
+ GNUTLS_CRT_PRINT_UNSIGNED_FULL = 2,
+ GNUTLS_CRT_PRINT_COMPACT = 3
} gnutls_certificate_print_formats_t;
#define GNUTLS_PK_ECC GNUTLS_PK_EC
@@ -1652,6 +1656,22 @@ gnutls_ecc_curve_t gnutls_ecc_curve_get(gnutls_session_t session);
int gnutls_hex2bin (const char *hex_data, size_t hex_size,
void *bin_data, size_t * bin_size);
+ /* ssh style functions */
+ int gnutls_verify_stored_pubkey(const char* file,
+ const char* application,
+ const char* host,
+ const char* service,
+ gnutls_certificate_type_t cert_type,
+ const gnutls_datum_t * cert, unsigned int flags);
+
+ int gnutls_store_pubkey(const char* file,
+ const char* application,
+ const char* host,
+ const char* service,
+ gnutls_certificate_type_t cert_type,
+ const gnutls_datum_t * cert, unsigned int flags);
+
+
/* Gnutls error codes. The mapping to a TLS alert is also shown in
* comments.
*/
diff --git a/lib/libgnutls.map b/lib/libgnutls.map
index e169a06170..40765f8d54 100644
--- a/lib/libgnutls.map
+++ b/lib/libgnutls.map
@@ -771,6 +771,8 @@ GNUTLS_3_0_0 {
gnutls_priority_protocol_list;
gnutls_priority_compression_list;
gnutls_priority_ecc_curve_list;
+ gnutls_verify_stored_pubkey;
+ gnutls_store_pubkey;
} GNUTLS_2_12;
GNUTLS_PRIVATE {
diff --git a/lib/openpgp/output.c b/lib/openpgp/output.c
index fdd176ac3a..88f522db70 100644
--- a/lib/openpgp/output.c
+++ b/lib/openpgp/output.c
@@ -506,6 +506,13 @@ gnutls_openpgp_crt_print (gnutls_openpgp_crt_t cert,
if (format == GNUTLS_CRT_PRINT_ONELINE)
print_oneline (&str, cert);
+ else if (format == GNUTLS_CRT_PRINT_COMPACT)
+ {
+ print_oneline (&str, cert);
+
+ _gnutls_buffer_append_data (&str, "\n", 1);
+ print_key_fingerprint (&str, cert);
+ }
else
{
_gnutls_buffer_append_str (&str,
diff --git a/lib/system.c b/lib/system.c
index eddb1053a4..476b313787 100644
--- a/lib/system.c
+++ b/lib/system.c
@@ -25,14 +25,20 @@
#include <gnutls_errors.h>
#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
#ifdef _WIN32
-#include <windows.h>
+# include <windows.h>
#else
-#ifdef HAVE_PTHREAD_LOCKS
-#include <pthread.h>
-#endif
+# ifdef HAVE_PTHREAD_LOCKS
+# include <pthread.h>
+# endif
+
+# if defined(HAVE_GETPWUID_R)
+# include <pwd.h>
+# endif
#endif
/* We need to disable gnulib's replacement wrappers to get native
@@ -278,3 +284,65 @@ mutex_init_func gnutls_mutex_init = gnutls_system_mutex_init;
mutex_deinit_func gnutls_mutex_deinit = gnutls_system_mutex_deinit;
mutex_lock_func gnutls_mutex_lock = gnutls_system_mutex_lock;
mutex_unlock_func gnutls_mutex_unlock = gnutls_system_mutex_unlock;
+
+#define CONFIG_PATH ".gnutls"
+
+/* Returns a path to store user-specific configuration
+ * data.
+ */
+int _gnutls_find_config_path(char* path, size_t max_size)
+{
+char tmp_home_dir[1024];
+const char *home_dir = getenv ("HOME");
+
+#ifdef _WIN32
+ if (home_dir == NULL || home_dir[0] == '\0')
+ {
+ const char *home_drive = getenv ("HOMEDRIVE");
+ const char *home_path = getenv ("HOMEPATH");
+
+ if (home_drive != NULL && home_path != NULL)
+ {
+ snprintf(tmp_home_dir, sizeof(tmp_home_dir), "%s%s", home_drive, home_path);
+ }
+ else
+ {
+ tmp_home_dir[0] = 0;
+ }
+
+ home_dir = tmp_home_dir;
+ }
+#elsif defined(HAVE_GETPWUID_R)
+ if (home_dir == NULL || home_dir[0] == '\0')
+ {
+ struct passwd *pwd;
+ struct passwd _pwd;
+ char buf[1024];
+
+ getpwuid_r(getuid(), &_pwd, buf, sizeof(buf), &pwd);
+ if (pwd != NULL)
+ {
+ snprintf(tmp_home_dir, sizeof(tmp_home_dir), "%s", pwd->pw_dir);
+ }
+ else
+ {
+ tmp_home_dir[0] = 0;
+ }
+
+ home_dir = tmp_home_dir;
+ }
+#else
+ if (home_dir == NULL || home_dir[0] == '\0')
+ {
+ tmp_home_dir[0] = 0;
+ home_dir = tmp_home_dir;
+ }
+#endif
+
+ if (home_dir == NULL || home_dir[0] == 0)
+ path[0] = 0;
+ else
+ snprintf(path, max_size, "%s/"CONFIG_PATH, home_dir);
+
+ return 0;
+}
diff --git a/lib/system.h b/lib/system.h
index df4ee5a36d..0d2f5a501f 100644
--- a/lib/system.h
+++ b/lib/system.h
@@ -71,4 +71,6 @@ struct timespec ts;
#endif
}
+int _gnutls_find_config_path(char* path, size_t max_size);
+
#endif /* SYSTEM_H */
diff --git a/lib/verify-ssh.c b/lib/verify-ssh.c
new file mode 100644
index 0000000000..8d6562f705
--- /dev/null
+++ b/lib/verify-ssh.c
@@ -0,0 +1,489 @@
+/*
+ * Copyright (C) 2012 Free Software Foundation, Inc.
+ *
+ * Author: Nikos Mavrogiannopoulos
+ *
+ * This file is part of GnuTLS.
+ *
+ * The GnuTLS 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 3 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 program. If not, see <http://www.gnu.org/licenses/>
+ *
+ */
+
+#include <gnutls_int.h>
+#include <gnutls_errors.h>
+#include <libtasn1.h>
+#include <gnutls_global.h>
+#include <gnutls_num.h> /* MAX */
+#include <gnutls_sig.h>
+#include <gnutls_str.h>
+#include <gnutls_datum.h>
+#include <hash.h>
+#include "x509_int.h"
+#include <common.h>
+#include <base64.h>
+#include <gnutls/abstract.h>
+#include <system.h>
+
+static int raw_pubkey_to_base64(gnutls_datum_t* pubkey);
+static int x509_crt_to_raw_pubkey(const gnutls_datum_t * cert, gnutls_datum_t *rpubkey);
+static int pgp_crt_to_raw_pubkey(const gnutls_datum_t * cert, gnutls_datum_t *rpubkey);
+static int find_stored_pubkey(const char* file, const char* application,
+ const char* host, const char* service,
+ const gnutls_datum_t* skey);
+static int find_config_file(char* file, size_t max_size);
+#define MAX_FILENAME 512
+
+/**
+ * gnutls_verify_stored_pubkey:
+ * @file: A file specifying the stored keys (use NULL for the default)
+ * @application: non-NULL with an application name if this key is application-specific
+ * @host: The peer's name
+ * @service: non-NULL if this key is specific to a service (e.g. http)
+ * @cert_type: The type of the certificate
+ * @cert: The raw (der) data of the certificate
+ * @flags: should be 0.
+ *
+ * This function will try to verify the provided certificate using
+ * a list of stored public keys. The @service field if non-NULL should
+ * be a port number.
+ *
+ * Returns: If no associated public key is found
+ * then %GNUTLS_E_NO_CERTIFICATE_FOUND will be returned. If a key
+ * is found but does not match %GNUTLS_E_CERTIFICATE_KEY_MISMATCH
+ * is returned. On success, %GNUTLS_E_SUCCESS (0) is returned,
+ * or a negative error value on other errors.
+ *
+ * Since: 3.0.0
+ **/
+int
+gnutls_verify_stored_pubkey(const char* file,
+ const char* application,
+ const char* host,
+ const char* service,
+ gnutls_certificate_type_t cert_type,
+ const gnutls_datum_t * cert, unsigned int flags)
+{
+gnutls_datum_t pubkey = { NULL, 0 };
+int ret;
+char local_file[MAX_FILENAME];
+
+ if (cert_type != GNUTLS_CRT_X509 && cert_type != GNUTLS_CRT_OPENPGP)
+ return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE);
+
+ if (file == NULL)
+ {
+ ret = find_config_file(local_file, sizeof(local_file));
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+ file = local_file;
+ }
+
+ if (cert_type == GNUTLS_CRT_X509)
+ ret = x509_crt_to_raw_pubkey(cert, &pubkey);
+ else
+ ret = pgp_crt_to_raw_pubkey(cert, &pubkey);
+
+ if (ret < 0)
+ {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ ret = raw_pubkey_to_base64(&pubkey);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ ret = find_stored_pubkey(file, application, host, service, &pubkey);
+ if (ret < 0)
+ return gnutls_assert_val(GNUTLS_E_NO_CERTIFICATE_FOUND);
+
+
+cleanup:
+ gnutls_free(pubkey.data);
+ return ret;
+}
+
+static int parse_line(char* line, const char* application,
+ size_t application_len,
+ const char* host, size_t host_len,
+ const char* service, size_t service_len,
+ const gnutls_datum_t *skey)
+{
+char* p, *kp;
+char* savep = NULL;
+size_t kp_len;
+
+ /* read version */
+ p = strtok_r(line, "|", &savep);
+ if (p == NULL)
+ return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
+
+ if (strncmp(p, "g0", 2) != 0)
+ return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
+
+ /* read application */
+ p = strtok_r(NULL, "|", &savep);
+ if (p == NULL)
+ return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
+
+ if (p[0] != '*' && strcmp(p, application)!=0)
+ return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
+
+ /* read host */
+ p = strtok_r(NULL, "|", &savep);
+ if (p == NULL)
+ return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
+
+ if (p[0] != '*' && strcmp(p, host) != 0)
+ return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
+
+ /* read service */
+ p = strtok_r(NULL, "|", &savep);
+ if (p == NULL)
+ return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
+
+ if (p[0] != '*' && strcmp(p, service) != 0)
+ return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
+
+ /* read service */
+ kp = strtok_r(NULL, "|", &savep);
+ if (kp == NULL)
+ return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
+
+ p = strpbrk(kp, "\n \r\t|");
+ if (p != NULL) *p = 0;
+
+ kp_len = strlen(kp);
+ if (kp_len != skey->size)
+ return gnutls_assert_val(GNUTLS_E_CERTIFICATE_KEY_MISMATCH);
+
+ if (memcmp(kp, skey->data, skey->size) != 0)
+ return gnutls_assert_val(GNUTLS_E_CERTIFICATE_KEY_MISMATCH);
+
+ /* key found and matches */
+ return 0;
+}
+
+/* Returns the base64 key if found
+ */
+static int find_stored_pubkey(const char* file, const char* application,
+ const char* host, const char* service,
+ const gnutls_datum_t* skey)
+{
+FILE* fd;
+char* line = NULL;
+size_t line_size = 0;
+int ret, l2, mismatch = 0;
+size_t application_len = 0, host_len = 0, service_len = 0;
+
+ if (host != NULL) host_len = strlen(host);
+ if (service != NULL) service_len = strlen(service);
+ if (application != NULL) application_len = strlen(application);
+
+ fd = fopen(file, "rb");
+ if (fd == NULL)
+ return gnutls_assert_val(GNUTLS_E_FILE_ERROR);
+
+ do
+ {
+ l2 = getline(&line, &line_size, fd);
+ if (l2 > 0)
+ {
+ ret = parse_line(line, application, application_len,
+ host, host_len, service, service_len, skey);
+ if (ret == 0) /* found */
+ {
+ goto cleanup;
+ }
+ else if (ret == GNUTLS_E_CERTIFICATE_KEY_MISMATCH)
+ mismatch = 1;
+ }
+ }
+ while(l2 >= 0);
+
+ if (mismatch)
+ ret = GNUTLS_E_CERTIFICATE_KEY_MISMATCH;
+ else
+ ret = GNUTLS_E_NO_CERTIFICATE_FOUND;
+
+cleanup:
+ free(line);
+ fclose(fd);
+
+ return ret;
+}
+
+static int raw_pubkey_to_base64(gnutls_datum_t* pubkey)
+{
+ int ret;
+ char* out;
+
+ ret = base64_encode_alloc((void*)pubkey->data, pubkey->size, &out);
+ if (ret == 0)
+ return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+
+ gnutls_free(pubkey->data);
+ pubkey->data = (void*)out;
+ pubkey->size = ret;
+
+ return 0;
+}
+
+static int x509_crt_to_raw_pubkey(const gnutls_datum_t * cert, gnutls_datum_t *rpubkey)
+{
+gnutls_x509_crt_t crt = NULL;
+gnutls_pubkey_t pubkey = NULL;
+size_t size;
+int ret;
+
+ ret = gnutls_x509_crt_init(&crt);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ ret = gnutls_pubkey_init(&pubkey);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ ret = gnutls_x509_crt_import(crt, cert, GNUTLS_X509_FMT_DER);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ ret = gnutls_pubkey_import_x509 (pubkey, crt, 0);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ size = 0;
+ ret = gnutls_pubkey_export(pubkey, GNUTLS_X509_FMT_DER, NULL, &size);
+ if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
+ {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ rpubkey->data = gnutls_malloc(size);
+ if (rpubkey->data == NULL)
+ if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
+ {
+ ret = GNUTLS_E_MEMORY_ERROR;
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ ret = gnutls_pubkey_export(pubkey, GNUTLS_X509_FMT_DER, rpubkey->data, &size);
+ if (ret < 0)
+ {
+ gnutls_free(rpubkey->data);
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ rpubkey->size = size;
+ ret = 0;
+
+cleanup:
+ gnutls_x509_crt_deinit(crt);
+ gnutls_pubkey_deinit(pubkey);
+
+ return ret;
+}
+
+static int pgp_crt_to_raw_pubkey(const gnutls_datum_t * cert, gnutls_datum_t *rpubkey)
+{
+gnutls_openpgp_crt_t crt = NULL;
+gnutls_pubkey_t pubkey = NULL;
+size_t size;
+int ret;
+
+ ret = gnutls_openpgp_crt_init(&crt);
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ ret = gnutls_pubkey_init(&pubkey);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ ret = gnutls_openpgp_crt_import(crt, cert, GNUTLS_OPENPGP_FMT_RAW);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ ret = gnutls_pubkey_import_openpgp (pubkey, crt, 0);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ size = 0;
+ ret = gnutls_pubkey_export(pubkey, GNUTLS_X509_FMT_DER, NULL, &size);
+ if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
+ {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ rpubkey->data = gnutls_malloc(size);
+ if (rpubkey->data == NULL)
+ if (ret < 0 && ret != GNUTLS_E_SHORT_MEMORY_BUFFER)
+ {
+ ret = GNUTLS_E_MEMORY_ERROR;
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ ret = gnutls_pubkey_export(pubkey, GNUTLS_X509_FMT_DER, rpubkey->data, &size);
+ if (ret < 0)
+ {
+ gnutls_free(rpubkey->data);
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ rpubkey->size = size;
+ ret = 0;
+
+cleanup:
+ gnutls_openpgp_crt_deinit(crt);
+ gnutls_pubkey_deinit(pubkey);
+
+ return ret;
+}
+
+/**
+ * gnutls_store_pubkey:
+ * @file: A file specifying the stored keys (use NULL for the default)
+ * @application: non-NULL with an application name if this key is application-specific
+ * @host: The peer's name
+ * @service: non-NULL if this key is specific to a service (e.g. http)
+ * @cert_type: The type of the certificate
+ * @cert: The data of the certificate
+ * @flags: should be 0.
+ *
+ * This function will store to verify the provided certificate to
+ * the list of stored public keys.
+ *
+ * Note that this function is not thread safe.
+ *
+ * Returns: On success, %GNUTLS_E_SUCCESS (0) is returned, otherwise a
+ * negative error value.
+ *
+ * Since: 3.0.0
+ **/
+int
+gnutls_store_pubkey(const char* file,
+ const char* application,
+ const char* host,
+ const char* service,
+ gnutls_certificate_type_t cert_type,
+ const gnutls_datum_t * cert, unsigned int flags)
+{
+FILE* fd = NULL;
+gnutls_datum_t pubkey = { NULL, 0 };
+int ret;
+char local_file[MAX_FILENAME];
+
+ if (cert_type != GNUTLS_CRT_X509 && cert_type != GNUTLS_CRT_OPENPGP)
+ return gnutls_assert_val(GNUTLS_E_UNSUPPORTED_CERTIFICATE_TYPE);
+
+ if (file == NULL)
+ {
+ ret = _gnutls_find_config_path(local_file, sizeof(local_file));
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ _gnutls_debug_log("Configuration path: %s\n", local_file);
+ mkdir(local_file, 0700);
+
+ ret = find_config_file(local_file, sizeof(local_file));
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+ file = local_file;
+ }
+
+ if (cert_type == GNUTLS_CRT_X509)
+ ret = x509_crt_to_raw_pubkey(cert, &pubkey);
+ else
+ ret = pgp_crt_to_raw_pubkey(cert, &pubkey);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ ret = raw_pubkey_to_base64(&pubkey);
+ if (ret < 0)
+ {
+ gnutls_assert();
+ goto cleanup;
+ }
+
+ _gnutls_debug_log("Configuration file: %s\n", file);
+
+ fd = fopen(file, "ab+");
+ if (fd == NULL)
+ {
+ ret = gnutls_assert_val(GNUTLS_E_FILE_ERROR);
+ goto cleanup;
+ }
+
+ if (application == NULL) application = "*";
+ if (service == NULL) service = "*";
+ if (host == NULL) host = "*";
+
+ fprintf(fd, "|g0|%s|%s|%s|%.*s\n", application, host, service, pubkey.size, pubkey.data);
+
+ ret = 0;
+
+cleanup:
+ gnutls_free(pubkey.data);
+ if (fd != NULL) fclose(fd);
+
+ return ret;
+}
+
+#define CONFIG_FILE "known_hosts"
+
+static int find_config_file(char* file, size_t max_size)
+{
+char path[MAX_FILENAME];
+int ret;
+
+ ret = _gnutls_find_config_path(path, sizeof(path));
+ if (ret < 0)
+ return gnutls_assert_val(ret);
+
+ if (path[0] == 0)
+ snprintf(file, max_size, "%s", CONFIG_FILE);
+ else
+ snprintf(file, max_size, "%s/%s", path, CONFIG_FILE);
+
+ return 0;
+}
diff --git a/lib/x509/output.c b/lib/x509/output.c
index 564004fb35..827845f427 100644
--- a/lib/x509/output.c
+++ b/lib/x509/output.c
@@ -1700,6 +1700,22 @@ gnutls_x509_crt_print (gnutls_x509_crt_t cert,
return ret;
}
+ else if (format == GNUTLS_CRT_PRINT_COMPACT)
+ {
+ _gnutls_buffer_init (&str);
+
+ print_oneline (&str, cert);
+
+ _gnutls_buffer_append_data (&str, "\n", 1);
+ print_keyid (&str, cert);
+
+ _gnutls_buffer_append_data (&str, "\0", 1);
+
+ ret = _gnutls_buffer_to_datum( &str, out);
+ if (out->size > 0) out->size--;
+
+ return ret;
+ }
else if (format == GNUTLS_CRT_PRINT_ONELINE)
{
_gnutls_buffer_init (&str);