diff options
Diffstat (limited to 'app/openvpn/src/openvpn/ssl_verify_polarssl.c')
-rw-r--r-- | app/openvpn/src/openvpn/ssl_verify_polarssl.c | 178 |
1 files changed, 86 insertions, 92 deletions
diff --git a/app/openvpn/src/openvpn/ssl_verify_polarssl.c b/app/openvpn/src/openvpn/ssl_verify_polarssl.c index a32db8df..71d38a9d 100644 --- a/app/openvpn/src/openvpn/ssl_verify_polarssl.c +++ b/app/openvpn/src/openvpn/ssl_verify_polarssl.c @@ -38,17 +38,19 @@ #if defined(ENABLE_SSL) && defined(ENABLE_CRYPTO_POLARSSL) #include "ssl_verify.h" +#include <polarssl/error.h> +#include <polarssl/bignum.h> +#include <polarssl/oid.h> #include <polarssl/sha1.h> #define MAX_SUBJECT_LENGTH 256 int -verify_callback (void *session_obj, x509_cert *cert, int cert_depth, - int preverify_ok) +verify_callback (void *session_obj, x509_crt *cert, int cert_depth, + int *flags) { struct tls_session *session = (struct tls_session *) session_obj; struct gc_arena gc = gc_new(); - int ret = 1; ASSERT (cert); ASSERT (session); @@ -59,31 +61,29 @@ verify_callback (void *session_obj, x509_cert *cert, int cert_depth, cert_hash_remember (session, cert_depth, x509_get_sha1_hash(cert, &gc)); /* did peer present cert which was signed by our root cert? */ - if (!preverify_ok) + if (*flags != 0) { char *subject = x509_get_subject(cert, &gc); if (subject) - msg (D_TLS_ERRORS, "VERIFY ERROR: depth=%d, %s", cert_depth, subject); + msg (D_TLS_ERRORS, "VERIFY ERROR: depth=%d, flags=%x, %s", cert_depth, *flags, subject); else - msg (D_TLS_ERRORS, "VERIFY ERROR: depth=%d, could not extract X509 " - "subject string from certificate", cert_depth); + msg (D_TLS_ERRORS, "VERIFY ERROR: depth=%d, flags=%x, could not extract X509 " + "subject string from certificate", *flags, cert_depth); - goto cleanup; + /* Leave flags set to non-zero to indicate that the cert is not ok */ + } + else if (SUCCESS != verify_cert(session, cert, cert_depth)) + { + *flags |= BADCERT_OTHER; } - if (SUCCESS != verify_cert(session, cert, cert_depth)) - goto cleanup; - - ret = 0; - -cleanup: gc_free(&gc); /* - * PolarSSL expects 1 on failure, 0 on success + * PolarSSL-1.2.0+ expects 0 on anything except fatal errors. */ - return ret; + return 0; } #ifdef ENABLE_X509ALTUSERNAME @@ -91,8 +91,8 @@ cleanup: #endif result_t -x509_get_username (char *cn, int cn_len, - char *x509_username_field, x509_cert *cert) +backend_x509_get_username (char *cn, int cn_len, + char *x509_username_field, x509_crt *cert) { x509_name *name; @@ -103,7 +103,7 @@ x509_get_username (char *cn, int cn_len, /* Find common name */ while( name != NULL ) { - if( memcmp( name->oid.p, OID_CN, OID_SIZE(OID_CN) ) == 0) + if( memcmp( name->oid.p, OID_AT_CN, OID_SIZE(OID_AT_CN) ) == 0) break; name = name->next; @@ -126,23 +126,59 @@ x509_get_username (char *cn, int cn_len, } char * -x509_get_serial (x509_cert *cert, struct gc_arena *gc) +backend_x509_get_serial (openvpn_x509_cert_t *cert, struct gc_arena *gc) +{ + char *buf = NULL; + size_t buflen = 0; + mpi serial_mpi = { 0 }; + int retval = 0; + + /* Transform asn1 integer serial into PolarSSL MPI */ + mpi_init(&serial_mpi); + retval = mpi_read_binary(&serial_mpi, cert->serial.p, cert->serial.len); + if (retval < 0) + { + char errbuf[128]; + polarssl_strerror(retval, errbuf, sizeof(errbuf)); + + msg(M_WARN, "Failed to retrieve serial from certificate: %s.", errbuf); + return NULL; + } + + /* Determine decimal representation length, allocate buffer */ + mpi_write_string(&serial_mpi, 10, buf, &buflen); + buf = gc_malloc(buflen, true, gc); + + /* Write MPI serial as decimal string into buffer */ + retval = mpi_write_string(&serial_mpi, 10, buf, &buflen); + if (retval < 0) + { + char errbuf[128]; + polarssl_strerror(retval, errbuf, sizeof(errbuf)); + + msg(M_WARN, "Failed to write serial to string: %s.", errbuf); + return NULL; + } + + return buf; +} + +char * +backend_x509_get_serial_hex (openvpn_x509_cert_t *cert, struct gc_arena *gc) { - int ret = 0; - int i = 0; char *buf = NULL; size_t len = cert->serial.len * 3 + 1; buf = gc_malloc(len, true, gc); - if(x509parse_serial_gets(buf, len-1, &cert->serial) < 0) + if(x509_serial_gets(buf, len-1, &cert->serial) < 0) buf = NULL; return buf; } unsigned char * -x509_get_sha1_hash (x509_cert *cert, struct gc_arena *gc) +x509_get_sha1_hash (x509_crt *cert, struct gc_arena *gc) { unsigned char *sha1_hash = gc_malloc(SHA_DIGEST_LENGTH, false, gc); sha1(cert->tbs.p, cert->tbs.len, sha1_hash); @@ -150,14 +186,14 @@ x509_get_sha1_hash (x509_cert *cert, struct gc_arena *gc) } char * -x509_get_subject(x509_cert *cert, struct gc_arena *gc) +x509_get_subject(x509_crt *cert, struct gc_arena *gc) { char tmp_subject[MAX_SUBJECT_LENGTH] = {0}; char *subject = NULL; int ret = 0; - ret = x509parse_dn_gets( tmp_subject, MAX_SUBJECT_LENGTH-1, &cert->subject ); + ret = x509_dn_gets( tmp_subject, MAX_SUBJECT_LENGTH-1, &cert->subject ); if (ret > 0) { /* Allocate the required space for the subject */ @@ -187,70 +223,28 @@ x509_setenv (struct env_set *es, int cert_depth, openvpn_x509_cert_t *cert) while( name != NULL ) { char name_expand[64+8]; + const char *shortname; - if( name->oid.len == 2 && memcmp( name->oid.p, OID_X520, 2 ) == 0 ) + if( 0 == oid_get_attr_short_name(&name->oid, &shortname) ) { - switch( name->oid.p[2] ) - { - case X520_COMMON_NAME: - openvpn_snprintf (name_expand, sizeof(name_expand), "X509_%d_CN", - cert_depth); break; - - case X520_COUNTRY: - openvpn_snprintf (name_expand, sizeof(name_expand), "X509_%d_C", - cert_depth); break; - - case X520_LOCALITY: - openvpn_snprintf (name_expand, sizeof(name_expand), "X509_%d_L", - cert_depth); break; - - case X520_STATE: - openvpn_snprintf (name_expand, sizeof(name_expand), "X509_%d_ST", - cert_depth); break; - - case X520_ORGANIZATION: - openvpn_snprintf (name_expand, sizeof(name_expand), "X509_%d_O", - cert_depth); break; - - case X520_ORG_UNIT: - openvpn_snprintf (name_expand, sizeof(name_expand), "X509_%d_OU", - cert_depth); break; - - default: - openvpn_snprintf (name_expand, sizeof(name_expand), - "X509_%d_0x%02X", cert_depth, name->oid.p[2]); - break; - } + openvpn_snprintf (name_expand, sizeof(name_expand), "X509_%d_%s", + cert_depth, shortname); } - else if( name->oid.len == 8 && memcmp( name->oid.p, OID_PKCS9, 8 ) == 0 ) - { - switch( name->oid.p[8] ) - { - case PKCS9_EMAIL: - openvpn_snprintf (name_expand, sizeof(name_expand), - "X509_%d_emailAddress", cert_depth); break; - - default: - openvpn_snprintf (name_expand, sizeof(name_expand), - "X509_%d_0x%02X", cert_depth, name->oid.p[8]); - break; - } - } - else - { - openvpn_snprintf (name_expand, sizeof(name_expand), "X509_%d_\?\?", - cert_depth); - } - - for( i = 0; i < name->val.len; i++ ) + else + { + openvpn_snprintf (name_expand, sizeof(name_expand), "X509_%d_\?\?", + cert_depth); + } + + for( i = 0; i < name->val.len; i++ ) { - if( i >= (int) sizeof( s ) - 1 ) - break; + if( i >= (int) sizeof( s ) - 1 ) + break; - c = name->val.p[i]; - if( c < 32 || c == 127 || ( c > 128 && c < 160 ) ) - s[i] = '?'; - else s[i] = c; + c = name->val.p[i]; + if( c < 32 || c == 127 || ( c > 128 && c < 160 ) ) + s[i] = '?'; + else s[i] = c; } s[i] = '\0'; @@ -264,7 +258,7 @@ x509_setenv (struct env_set *es, int cert_depth, openvpn_x509_cert_t *cert) } result_t -x509_verify_ns_cert_type(const x509_cert *cert, const int usage) +x509_verify_ns_cert_type(const x509_crt *cert, const int usage) { if (usage == NS_CERT_CHECK_NONE) return SUCCESS; @@ -279,7 +273,7 @@ x509_verify_ns_cert_type(const x509_cert *cert, const int usage) } result_t -x509_verify_cert_ku (x509_cert *cert, const unsigned * const expected_ku, +x509_verify_cert_ku (x509_crt *cert, const unsigned * const expected_ku, int expected_len) { result_t fFound = FAILURE; @@ -312,7 +306,7 @@ x509_verify_cert_ku (x509_cert *cert, const unsigned * const expected_ku, } result_t -x509_verify_cert_eku (x509_cert *cert, const char * const expected_oid) +x509_verify_cert_eku (x509_crt *cert, const char * const expected_oid) { result_t fFound = FAILURE; @@ -362,7 +356,7 @@ x509_verify_cert_eku (x509_cert *cert, const char * const expected_oid) } result_t -x509_write_pem(FILE *peercert_file, x509_cert *peercert) +x509_write_pem(FILE *peercert_file, x509_crt *peercert) { msg (M_WARN, "PolarSSL does not support writing peer certificate in PEM format"); return FAILURE; @@ -372,12 +366,12 @@ x509_write_pem(FILE *peercert_file, x509_cert *peercert) * check peer cert against CRL */ result_t -x509_verify_crl(const char *crl_file, x509_cert *cert, const char *subject) +x509_verify_crl(const char *crl_file, x509_crt *cert, const char *subject) { result_t retval = FAILURE; x509_crl crl = {0}; - if (x509parse_crlfile(&crl, crl_file) != 0) + if (x509_crl_parse_file(&crl, crl_file) != 0) { msg (M_ERR, "CRL: cannot read CRL from file %s", crl_file); goto end; @@ -392,7 +386,7 @@ x509_verify_crl(const char *crl_file, x509_cert *cert, const char *subject) goto end; } - if (0 != x509parse_revoked(cert, &crl)) + if (0 != x509_crt_revoked(cert, &crl)) { msg (D_HANDSHAKE, "CRL CHECK FAILED: %s is REVOKED", subject); goto end; |