diff options
-rw-r--r-- | doc/openvpn.8 | 6 | ||||
-rw-r--r-- | src/openvpn/ssl_verify.c | 9 | ||||
-rw-r--r-- | src/openvpn/ssl_verify_backend.h | 21 | ||||
-rw-r--r-- | src/openvpn/ssl_verify_openssl.c | 10 | ||||
-rw-r--r-- | src/openvpn/ssl_verify_polarssl.c | 42 |
5 files changed, 81 insertions, 7 deletions
diff --git a/doc/openvpn.8 b/doc/openvpn.8 index ec56030..786719d 100644 --- a/doc/openvpn.8 +++ b/doc/openvpn.8 @@ -6054,6 +6054,12 @@ code should check that. See the contrib/OCSP_check/OCSP_check.sh script for an example. .\"********************************************************* .TP +.B tls_serial_hex_{n} +Like +.B tls_serial_{n}\fR, +but in hex form (e.g. "12:34:56:78:9A"). +.\"********************************************************* +.TP .B tun_mtu The MTU of the TUN/TAP device. Set prior to diff --git a/src/openvpn/ssl_verify.c b/src/openvpn/ssl_verify.c index 0670f2a..c90c2c3 100644 --- a/src/openvpn/ssl_verify.c +++ b/src/openvpn/ssl_verify.c @@ -435,10 +435,15 @@ verify_cert_set_env(struct env_set *es, openvpn_x509_cert_t *peer_cert, int cert } /* export serial number as environmental variable */ - serial = x509_get_serial(peer_cert, &gc); + serial = backend_x509_get_serial(peer_cert, &gc); openvpn_snprintf (envname, sizeof(envname), "tls_serial_%d", cert_depth); setenv_str (es, envname, serial); + /* export serial number in hex as environmental variable */ + serial = backend_x509_get_serial_hex(peer_cert, &gc); + openvpn_snprintf (envname, sizeof(envname), "tls_serial_hex_%d", cert_depth); + setenv_str (es, envname, serial); + gc_free(&gc); } @@ -562,7 +567,7 @@ verify_check_crl_dir(const char *crl_dir, openvpn_x509_cert_t *cert) int fd = -1; struct gc_arena gc = gc_new(); - char *serial = x509_get_serial(cert, &gc); + char *serial = backend_x509_get_serial(cert, &gc); if (!openvpn_snprintf(fn, sizeof(fn), "%s%c%s", crl_dir, OS_SPECIFIC_DIRSEP, serial)) { diff --git a/src/openvpn/ssl_verify_backend.h b/src/openvpn/ssl_verify_backend.h index 1658cc0..6f118c9 100644 --- a/src/openvpn/ssl_verify_backend.h +++ b/src/openvpn/ssl_verify_backend.h @@ -113,16 +113,31 @@ result_t x509_get_username (char *common_name, int cn_len, char * x509_username_field, openvpn_x509_cert_t *peer_cert); /* - * Return the certificate's serial number. + * Return the certificate's serial number in decimal string representation. * * The serial number is returned as a string, since it might be a bignum. * * @param cert Certificate to retrieve the serial number from. * @param gc Garbage collection arena to use when allocating string. * - * @return The certificate's serial number. + * @return String representation of the certificate's serial number + * in decimal notation, or NULL on error. */ -char *x509_get_serial (openvpn_x509_cert_t *cert, struct gc_arena *gc); +char *backend_x509_get_serial (openvpn_x509_cert_t *cert, struct gc_arena *gc); + +/* + * Return the certificate's serial number in hex string representation. + * + * The serial number is returned as a string, since it might be a bignum. + * + * @param cert Certificate to retrieve the serial number from. + * @param gc Garbage collection arena to use when allocating string. + * + * @return String representation of the certificate's serial number + * in hex notation, or NULL on error. + */ +char *backend_x509_get_serial_hex (openvpn_x509_cert_t *cert, + struct gc_arena *gc); /* * Save X509 fields to environment, using the naming convention: diff --git a/src/openvpn/ssl_verify_openssl.c b/src/openvpn/ssl_verify_openssl.c index 91a42b2..19982ae 100644 --- a/src/openvpn/ssl_verify_openssl.c +++ b/src/openvpn/ssl_verify_openssl.c @@ -220,7 +220,7 @@ x509_get_username (char *common_name, int cn_len, } char * -x509_get_serial (openvpn_x509_cert_t *cert, struct gc_arena *gc) +backend_x509_get_serial (openvpn_x509_cert_t *cert, struct gc_arena *gc) { ASN1_INTEGER *asn1_i; BIGNUM *bignum; @@ -238,6 +238,14 @@ x509_get_serial (openvpn_x509_cert_t *cert, struct gc_arena *gc) return serial; } +char * +backend_x509_get_serial_hex (openvpn_x509_cert_t *cert, struct gc_arena *gc) +{ + const ASN1_INTEGER *asn1_i = X509_get_serialNumber(cert); + + return format_hex_ex(asn1_i->data, asn1_i->length, 0, 1, ":", gc); +} + unsigned char * x509_get_sha1_hash (X509 *cert, struct gc_arena *gc) { diff --git a/src/openvpn/ssl_verify_polarssl.c b/src/openvpn/ssl_verify_polarssl.c index 5db4f02..3fd861c 100644 --- a/src/openvpn/ssl_verify_polarssl.c +++ b/src/openvpn/ssl_verify_polarssl.c @@ -38,6 +38,8 @@ #if defined(ENABLE_SSL) && defined(ENABLE_CRYPTO_POLARSSL) #include "ssl_verify.h" +#include <polarssl/error.h> +#include <polarssl/bignum.h> #include <polarssl/sha1.h> #define MAX_SUBJECT_LENGTH 256 @@ -123,11 +125,49 @@ 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) { int ret = 0; int i = 0; 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]; + error_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]; + error_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) +{ + char *buf = NULL; size_t len = cert->serial.len * 3 + 1; buf = gc_malloc(len, true, gc); |