summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/cha-cert-auth.texi13
-rw-r--r--doc/cha-gtls-examples.texi5
-rw-r--r--doc/examples/ex-verify-ssh.c8
-rw-r--r--lib/includes/gnutls/gnutls.h.in6
-rw-r--r--lib/verify-ssh.c51
5 files changed, 44 insertions, 39 deletions
diff --git a/doc/cha-cert-auth.texi b/doc/cha-cert-auth.texi
index 7fb41a60dd..a2656ad94d 100644
--- a/doc/cha-cert-auth.texi
+++ b/doc/cha-cert-auth.texi
@@ -87,7 +87,7 @@ acceptable. The framework is illustrated on @ref{fig:x509}.
* X.509 distinguished names::
* Verifying X.509 certificate paths::
* Verifying a certificate in the context of TLS session::
-* Verifying a certificate using SSH-style authentication::
+* Verifying a certificate using trust on first use authentication::
@end menu
@node X.509 certificate structure
@@ -277,15 +277,16 @@ about the peer's identity. It is required to verify if the
certificate's owner is the one you expect. For more information
consult @xcite{RFC2818} and section @ref{ex:verify} for an example.
-@node Verifying a certificate using SSH-style authentication
-@subsection Verifying a certificate using SSH-style authentication
+@node Verifying a certificate using trust on first use authentication
+@subsection Verifying a certificate using trust on first use authentication
@cindex verifying certificate paths
@cindex SSH-style authentication
+@cindex Trust on first use
@tindex gnutls_certificate_verify_flags
-It is possible to use an SSH-style authentication method in GnuTLS.
-That means that having seen and associated a public key with a host
-is enough to trust it on the subsequent connections.
+It is possible to use a trust on first use (similar to SSH) authentication
+method in GnuTLS. That means that having seen and associated a public key
+with a host is enough to trust it on the subsequent connections.
A hybrid system with X.509 and SSH authentication is
shown in @ref{Simple client example with SSH-style certificate verification}.
diff --git a/doc/cha-gtls-examples.texi b/doc/cha-gtls-examples.texi
index 9d253a0045..637653c46a 100644
--- a/doc/cha-gtls-examples.texi
+++ b/doc/cha-gtls-examples.texi
@@ -70,8 +70,9 @@ resumption.
This is an alternative verification function that will use the
X.509 certificate authorities for verification, but also assume an
-SSH-like authentication system. That is the user is prompted on unknown
-public keys and known public keys are considered trusted.
+trust on first use (SSH-like) authentication system. That is the user is
+prompted on unknown public keys and known public keys are considered
+trusted.
@verbatiminclude examples/ex-verify-ssh.c
diff --git a/doc/examples/ex-verify-ssh.c b/doc/examples/ex-verify-ssh.c
index c9a66b27bc..fb211c5746 100644
--- a/doc/examples/ex-verify-ssh.c
+++ b/doc/examples/ex-verify-ssh.c
@@ -92,8 +92,10 @@ _ssh_verify_certificate_callback (gnutls_session_t session)
gnutls_x509_crt_deinit (cert);
- ret = gnutls_verify_stored_pubkey(NULL, NULL, hostname, "443",
- GNUTLS_CRT_X509, &cert_list[0], 0);
+ /* service may be obtained alternatively using getservbyport() */
+ ret = gnutls_verify_stored_pubkey(NULL, hostname, "https",
+ GNUTLS_CRT_X509, &cert_list[0],
+ 0, 0);
if (ret == GNUTLS_E_NO_CERTIFICATE_FOUND)
{
fprintf(stderr, "Host %s is not known.", hostname);
@@ -128,7 +130,7 @@ _ssh_verify_certificate_callback (gnutls_session_t session)
/* user trusts the key -> store it */
if (ret != 0)
{
- ret = gnutls_store_pubkey(NULL, NULL, hostname, "443", GNUTLS_CRT_X509, &cert_list[0], 0);
+ ret = gnutls_store_pubkey(NULL, hostname, "https", GNUTLS_CRT_X509, &cert_list[0], 0);
if (ret < 0)
fprintf(stderr, "gnutls_store_pubkey: %s\n", gnutls_strerror(ret));
}
diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in
index 415e282719..f5adbf5863 100644
--- a/lib/includes/gnutls/gnutls.h.in
+++ b/lib/includes/gnutls/gnutls.h.in
@@ -1658,18 +1658,18 @@ gnutls_ecc_curve_t gnutls_ecc_curve_get(gnutls_session_t session);
/* 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);
+ const gnutls_datum_t * cert,
+ time_t expiration,
+ unsigned int flags);
/* Gnutls error codes. The mapping to a TLS alert is also shown in
diff --git a/lib/verify-ssh.c b/lib/verify-ssh.c
index 8d6562f705..23ac819e62 100644
--- a/lib/verify-ssh.c
+++ b/lib/verify-ssh.c
@@ -38,7 +38,7 @@
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,
+static int find_stored_pubkey(const char* file,
const char* host, const char* service,
const gnutls_datum_t* skey);
static int find_config_file(char* file, size_t max_size);
@@ -47,7 +47,6 @@ static int find_config_file(char* file, size_t max_size);
/**
* 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
@@ -68,7 +67,6 @@ static int find_config_file(char* file, size_t max_size);
**/
int
gnutls_verify_stored_pubkey(const char* file,
- const char* application,
const char* host,
const char* service,
gnutls_certificate_type_t cert_type,
@@ -107,7 +105,7 @@ char local_file[MAX_FILENAME];
goto cleanup;
}
- ret = find_stored_pubkey(file, application, host, service, &pubkey);
+ ret = find_stored_pubkey(file, host, service, &pubkey);
if (ret < 0)
return gnutls_assert_val(GNUTLS_E_NO_CERTIFICATE_FOUND);
@@ -117,15 +115,16 @@ cleanup:
return ret;
}
-static int parse_line(char* line, const char* application,
- size_t application_len,
+static int parse_line(char* line,
const char* host, size_t host_len,
const char* service, size_t service_len,
+ time_t now,
const gnutls_datum_t *skey)
{
char* p, *kp;
char* savep = NULL;
size_t kp_len;
+time_t expiration;
/* read version */
p = strtok_r(line, "|", &savep);
@@ -135,31 +134,32 @@ size_t kp_len;
if (strncmp(p, "g0", 2) != 0)
return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
- /* read application */
+ /* read host */
p = strtok_r(NULL, "|", &savep);
if (p == NULL)
return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
- if (p[0] != '*' && strcmp(p, application)!=0)
+ if (p[0] != '*' && strcmp(p, host) != 0)
return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
- /* read host */
+ /* read service */
p = strtok_r(NULL, "|", &savep);
if (p == NULL)
return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
- if (p[0] != '*' && strcmp(p, host) != 0)
+ if (p[0] != '*' && strcmp(p, service) != 0)
return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
- /* read service */
+ /* read expiration */
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);
+ expiration = (time_t)atol(p);
+ if (expiration > 0 && now > expiration)
+ return gnutls_assert_val(GNUTLS_E_EXPIRED);
- /* read service */
+ /* read key */
kp = strtok_r(NULL, "|", &savep);
if (kp == NULL)
return gnutls_assert_val(GNUTLS_E_PARSING_ERROR);
@@ -180,7 +180,7 @@ size_t kp_len;
/* Returns the base64 key if found
*/
-static int find_stored_pubkey(const char* file, const char* application,
+static int find_stored_pubkey(const char* file,
const char* host, const char* service,
const gnutls_datum_t* skey)
{
@@ -188,11 +188,11 @@ 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;
+size_t host_len = 0, service_len = 0;
+time_t now = gnutls_time(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)
@@ -203,8 +203,7 @@ size_t application_len = 0, host_len = 0, service_len = 0;
l2 = getline(&line, &line_size, fd);
if (l2 > 0)
{
- ret = parse_line(line, application, application_len,
- host, host_len, service, service_len, skey);
+ ret = parse_line(line, host, host_len, service, service_len, now, skey);
if (ret == 0) /* found */
{
goto cleanup;
@@ -380,15 +379,16 @@ cleanup:
/**
* 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
+ * @expiration: The expiration time (use 0 to disable expiration)
* @flags: should be 0.
*
* This function will store to verify the provided certificate to
- * the list of stored public keys.
+ * the list of stored public keys. The key will be considered valid until
+ * the provided expiration time.
*
* Note that this function is not thread safe.
*
@@ -399,11 +399,12 @@ cleanup:
**/
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)
+ const gnutls_datum_t * cert,
+ time_t expiration,
+ unsigned int flags)
{
FILE* fd = NULL;
gnutls_datum_t pubkey = { NULL, 0 };
@@ -454,11 +455,11 @@ char local_file[MAX_FILENAME];
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);
+ fprintf(fd, "|g0|%s|%s|%lu|%.*s\n", host, service, (unsigned long)expiration,
+ pubkey.size, pubkey.data);
ret = 0;