diff options
author | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2002-02-17 13:14:02 +0000 |
---|---|---|
committer | Nikos Mavrogiannopoulos <nmav@gnutls.org> | 2002-02-17 13:14:02 +0000 |
commit | ce6aa8a41c27aa071e42ac3af0386db4ee56cf39 (patch) | |
tree | f2476cf43066201c41847eb442520daa47afe088 | |
parent | f1957a53189d67745984b5381f886d577378e35c (diff) | |
download | gnutls-ce6aa8a41c27aa071e42ac3af0386db4ee56cf39.tar.gz |
Improved X.509 verification functions. They are still too primitive.
-rw-r--r-- | lib/gnutls_x509.c | 100 | ||||
-rw-r--r-- | lib/x509_verify.c | 53 |
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; |