summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Mavrogiannopoulos <nmav@gnutls.org>2002-02-17 13:14:02 +0000
committerNikos Mavrogiannopoulos <nmav@gnutls.org>2002-02-17 13:14:02 +0000
commitce6aa8a41c27aa071e42ac3af0386db4ee56cf39 (patch)
treef2476cf43066201c41847eb442520daa47afe088
parentf1957a53189d67745984b5381f886d577378e35c (diff)
downloadgnutls-ce6aa8a41c27aa071e42ac3af0386db4ee56cf39.tar.gz
Improved X.509 verification functions. They are still too primitive.
-rw-r--r--lib/gnutls_x509.c100
-rw-r--r--lib/x509_verify.c53
2 files changed, 140 insertions, 13 deletions
diff --git a/lib/gnutls_x509.c b/lib/gnutls_x509.c
index d6059b4ed1..982d11daf6 100644
--- a/lib/gnutls_x509.c
+++ b/lib/gnutls_x509.c
@@ -974,7 +974,6 @@ static int read_cert_mem(GNUTLS_CERTIFICATE_CREDENTIALS res, const char *cert, i
if (siz2 < 0) {
gnutls_assert();
- gnutls_free(b64);
return GNUTLS_E_PARSING_ERROR;
}
@@ -1047,7 +1046,6 @@ static int read_ca_mem(GNUTLS_CERTIFICATE_CREDENTIALS res, const char *ca, int c
if (siz2 < 0) {
gnutls_assert();
- gnutls_free(b64);
return GNUTLS_E_PARSING_ERROR;
}
@@ -1121,7 +1119,6 @@ static int read_key_mem(GNUTLS_CERTIFICATE_CREDENTIALS res, const char *key, int
if (siz < 0) {
gnutls_assert();
- gnutls_free(b64);
return GNUTLS_E_PARSING_ERROR;
}
@@ -1806,3 +1803,100 @@ int _gnutls_check_x509_key_usage(const gnutls_cert * cert,
}
return 0;
}
+
+
+#ifdef DEBUG
+/* Reads a base64 encoded CA list from memory
+ * This is to be called once.
+ */
+int _gnutls_verify_x509_mem( const char *ca, int ca_size)
+{
+ int siz, siz2, i;
+ opaque *b64;
+ const char *ptr;
+ int ret;
+ gnutls_datum tmp;
+ gnutls_cert* x509_ca_list=NULL;
+ int x509_ncas;
+
+ siz = ca_size;
+
+ ptr = ca;
+
+ i = 1;
+
+ do {
+ siz2 = _gnutls_fbase64_decode(ptr, siz, &b64);
+ siz -= siz2; /* FIXME: this is not enough
+ */
+
+ if (siz2 < 0) {
+ gnutls_assert();
+ return GNUTLS_E_PARSING_ERROR;
+ }
+
+ x509_ca_list =
+ (gnutls_cert *) gnutls_realloc( x509_ca_list,
+ i *
+ sizeof(gnutls_cert));
+ if (x509_ca_list == NULL) {
+ gnutls_assert();
+ gnutls_free(b64);
+ return GNUTLS_E_MEMORY_ERROR;
+ }
+ memset(&x509_ca_list[i - 1], 0, sizeof(gnutls_cert));
+
+ tmp.data = b64;
+ tmp.size = siz2;
+
+ if ((ret =
+ _gnutls_x509_cert2gnutls_cert(&x509_ca_list[i - 1],
+ tmp)) < 0) {
+ gnutls_assert();
+ gnutls_free(b64);
+ return ret;
+ }
+ gnutls_free(b64);
+
+ /* now we move ptr after the pem header */
+ ptr = strstr(ptr, CERT_SEP);
+ if (ptr!=NULL)
+ ptr++;
+
+ i++;
+ } while ((ptr = strstr(ptr, CERT_SEP)) != NULL);
+
+ x509_ncas = i - 1;
+
+ siz = _gnutls_x509_verify_certificate( x509_ca_list, x509_ncas-1,
+ &x509_ca_list[x509_ncas-1], 1, NULL, 0);
+
+ return siz;
+}
+
+
+
+/* Reads a base64 encoded CA file (file contains multiple certificate
+ * authorities). This is to be called once.
+ */
+int _gnutls_verify_x509_file( char *cafile)
+{
+ int siz;
+ char x[MAX_FILE_SIZE];
+ FILE *fd1;
+
+ fd1 = fopen(cafile, "r");
+ if (fd1 == NULL) {
+ gnutls_assert();
+ return GNUTLS_E_UNKNOWN_ERROR;
+ }
+
+ siz = fread(x, 1, sizeof(x), fd1);
+ fclose(fd1);
+
+ x[siz-1] = 0;
+
+ return _gnutls_verify_x509_mem( x, siz);
+}
+
+#endif
diff --git a/lib/x509_verify.c b/lib/x509_verify.c
index fcde32409d..55e9e17f9b 100644
--- a/lib/x509_verify.c
+++ b/lib/x509_verify.c
@@ -141,6 +141,8 @@ time_t _gnutls_generalTime2gtime(char *ttime)
return ret;
}
+/* Returns VALID or EXPIRED.
+ */
static int check_if_expired(gnutls_cert * cert)
{
CertificateStatus ret = GNUTLS_CERT_EXPIRED;
@@ -149,7 +151,32 @@ static int check_if_expired(gnutls_cert * cert)
*/
if (time(NULL) < cert->expiration_time)
- ret = GNUTLS_CERT_TRUSTED;
+ ret = GNUTLS_CERT_VALID;
+
+ return ret;
+}
+
+/* Return GNUTLS_CERT_VALID or INVALID, if the issuer is a CA,
+ * or not.
+ */
+static int check_if_ca(const gnutls_cert * cert, const gnutls_cert* issuer)
+{
+ CertificateStatus ret = GNUTLS_CERT_INVALID;
+
+ /* Check if the issuer is the same with the
+ * certificate. This is added in order for trusted
+ * certificates to be able to verify themselves.
+ */
+ if (cert->raw.size == issuer->raw.size) {
+ if ( memcmp( cert->raw.data, issuer->raw.data, cert->raw.size)==0) {
+ return GNUTLS_CERT_VALID;
+ }
+ }
+
+ if (issuer->CA==1) {
+ ret = GNUTLS_CERT_VALID;
+ } else
+ gnutls_assert();
return ret;
}
@@ -289,32 +316,38 @@ int gnutls_verify_certificate2(gnutls_cert * cert, gnutls_cert * trusted_cas, in
gnutls_assert();
return GNUTLS_CERT_INVALID;
}
+
+ ret = check_if_ca( cert, issuer);
+ if (ret != GNUTLS_CERT_VALID) {
+ gnutls_assert();
+ return ret;
+ }
ret = gnutls_x509_verify_signature(cert, issuer);
if (ret != GNUTLS_CERT_TRUSTED)
return ret;
- /* Check CRL --not done yet.
+ /* FIXME: Check CRL --not done yet.
*/
ret = check_if_expired( cert);
-
- if (ret == GNUTLS_CERT_EXPIRED)
+ if (ret != GNUTLS_CERT_VALID) {
+ gnutls_assert();
return ret;
+ }
return GNUTLS_CERT_TRUSTED;
}
/* The algorithm used is:
* 1. Check the certificate chain given by the peer, if it is ok.
- * 2. If any certificate in the chain are expired, revoked or not
- * valid, then the certificate is not trusted.
+ * 2. If any certificate in the chain are expired, revoked, not
+ * valid, or they are not CAs then the certificate is invalid.
* 3. If 1 is ok, then find a certificate in the trusted CAs file
* that has the DN of the issuer field in the last certificate
* in the peer's certificate chain.
* 4. If it does exist then verify it. If verification is ok then
- * it is trusted.
- * 5. In all other cases the certificate is not trusted.
+ * it is trusted. Otherwise it is just valid (but not trusted).
*/
/* This function verifies a X.509 certificate list. The certificate list should
* lead to a trusted CA in order to be trusted.
@@ -338,7 +371,7 @@ int _gnutls_x509_verify_certificate( gnutls_cert * certificate_list,
if ((ret = gnutls_verify_certificate2(&certificate_list[i], &certificate_list[i + 1], 1, NULL, 0)) != GNUTLS_CERT_TRUSTED) {
/*
- * We only accept the given certificate to be
+ * We only accept the first certificate to be
* expired. If any of the certificates in the
* certificate chain is expired then the certificate
* is not valid.
@@ -367,7 +400,7 @@ int _gnutls_x509_verify_certificate( gnutls_cert * certificate_list,
return ret;
/* Since the certificate chain is ok,
- * the certificate is valid.
+ * the certificate is valid (but not trusted).
*/
if (ret != GNUTLS_CERT_TRUSTED)
return GNUTLS_CERT_VALID;