mirror of
https://github.com/OpenVPN/openvpn3.git
synced 2024-09-20 12:12:15 +02:00
mbedtls: Move x509_get_subject() and x509_get_common_name() to an independent file
This is the mbed TLS counter part to the OpenSSL change in commit e0fd92f30756. These two methods are generic and not tied to the MbedTLSContext in any particular way. This is needed to be able to add a unit test for the x509_get_*() functions. Signed-off-by: David Sommerseth <davids@openvpn.net>
This commit is contained in:
parent
7900c71f5c
commit
fc060bd317
135
openvpn/mbedtls/pki/x509certinfo.hpp
Normal file
135
openvpn/mbedtls/pki/x509certinfo.hpp
Normal file
@ -0,0 +1,135 @@
|
|||||||
|
// OpenVPN -- An application to securely tunnel IP networks
|
||||||
|
// over a single port, with support for SSL/TLS-based
|
||||||
|
// session authentication and key exchange,
|
||||||
|
// packet encryption, packet authentication, and
|
||||||
|
// packet compression.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2012-2019 OpenVPN Inc.
|
||||||
|
//
|
||||||
|
// This program is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU Affero General Public License Version 3
|
||||||
|
// as published by the Free Software Foundation.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Affero General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
|
// along with this program in the COPYING file.
|
||||||
|
// If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include <mbedtls/x509.h>
|
||||||
|
#include <mbedtls/x509_crt.h>
|
||||||
|
#include <mbedtls/oid.h>
|
||||||
|
|
||||||
|
#include "openvpn/common/hexstr.hpp"
|
||||||
|
|
||||||
|
#define MBEDTLS_MAX_SUBJECT_LENGTH 256
|
||||||
|
|
||||||
|
namespace openvpn {
|
||||||
|
namespace MbedTLSPKI {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the complete X.509 Certificate Subject field
|
||||||
|
*
|
||||||
|
* OpenSSL supports two ways of representing the subject line. The old
|
||||||
|
* format is deprecated, but there might be code expecting this old format.
|
||||||
|
* The old format looks like this:
|
||||||
|
*
|
||||||
|
* /C=KG/ST=NA/O=OpenVPN-TEST/CN=Test-Server/emailAddress=me@myhost.mydomain
|
||||||
|
*
|
||||||
|
* The new format is UTF-8 compliant and has a different formatting scheme:
|
||||||
|
*
|
||||||
|
* C=KG, ST=NA, O=OpenVPN-TEST, CN=Test-Server,
|
||||||
|
*emailAddress=me@myhost.mydomain
|
||||||
|
*
|
||||||
|
* This mbed TLS implementation supports generating a subject line formatted
|
||||||
|
* as the deprecated OpenSSL format. This is the default behaviour, to
|
||||||
|
* preserve OpenSSL compatibility with existing OpenVPN code.
|
||||||
|
*
|
||||||
|
* @param cert Pointer to a native mbed TLS X509 object containing the
|
||||||
|
* certificate
|
||||||
|
* @param new_format (optional, default: false) Which format to use,
|
||||||
|
* true indicates the new format
|
||||||
|
*
|
||||||
|
* @return Returns a std::string containing the complete certificate subject.
|
||||||
|
* If it was not possible to retrieve the subject, and empty string
|
||||||
|
* is returned.
|
||||||
|
*/
|
||||||
|
static std::string x509_get_subject(const mbedtls_x509_crt *cert,
|
||||||
|
bool new_format = false) {
|
||||||
|
if (!new_format) {
|
||||||
|
// Try to return the x509 subject formatted like the OpenSSL
|
||||||
|
// X509_NAME_oneline method. Only attributes matched in the switch
|
||||||
|
// statements below will be rendered. All other attributes will be
|
||||||
|
// ignored.
|
||||||
|
|
||||||
|
std::string ret;
|
||||||
|
for (const mbedtls_x509_name *name = &cert->subject; name != nullptr;
|
||||||
|
name = name->next) {
|
||||||
|
const char *key = nullptr;
|
||||||
|
if (!MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &name->oid))
|
||||||
|
key = "CN";
|
||||||
|
else if (!MBEDTLS_OID_CMP(MBEDTLS_OID_AT_COUNTRY, &name->oid))
|
||||||
|
key = "C";
|
||||||
|
else if (!MBEDTLS_OID_CMP(MBEDTLS_OID_AT_LOCALITY, &name->oid))
|
||||||
|
key = "L";
|
||||||
|
else if (!MBEDTLS_OID_CMP(MBEDTLS_OID_AT_STATE, &name->oid))
|
||||||
|
key = "ST";
|
||||||
|
else if (!MBEDTLS_OID_CMP(MBEDTLS_OID_AT_ORGANIZATION, &name->oid))
|
||||||
|
key = "O";
|
||||||
|
else if (!MBEDTLS_OID_CMP(MBEDTLS_OID_AT_ORG_UNIT, &name->oid))
|
||||||
|
key = "OU";
|
||||||
|
else if (!MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS9_EMAIL, &name->oid))
|
||||||
|
key = "emailAddress";
|
||||||
|
|
||||||
|
// make sure that key is defined and value has no embedded nulls
|
||||||
|
if (key &&
|
||||||
|
!string::embedded_null((const char *)name->val.p, name->val.len))
|
||||||
|
ret += "/" + std::string(key) + "=" +
|
||||||
|
std::string((const char *)name->val.p, name->val.len);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
char tmp_subj[MBEDTLS_MAX_SUBJECT_LENGTH] = {0};
|
||||||
|
int ret = mbedtls_x509_dn_gets(tmp_subj, MBEDTLS_MAX_SUBJECT_LENGTH - 1,
|
||||||
|
&cert->subject);
|
||||||
|
return (ret > 0 ? std::string(tmp_subj) : std::string(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves just the common name of the X.509 Certificate subject field
|
||||||
|
*
|
||||||
|
* @param cert Pointer to a native mbedTLS X509 object containing the
|
||||||
|
* certificate
|
||||||
|
*
|
||||||
|
* @return Returns the contents of the extracted field on success. The
|
||||||
|
* resulting string may be empty if the extraction failed or the field
|
||||||
|
* is empty.
|
||||||
|
*/
|
||||||
|
static std::string x509_get_common_name(const mbedtls_x509_crt *cert) {
|
||||||
|
const mbedtls_x509_name *name = &cert->subject;
|
||||||
|
|
||||||
|
// find common name
|
||||||
|
while (name != nullptr) {
|
||||||
|
if (!MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &name->oid)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
name = name->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (name ? std::string((const char *)name->val.p, name->val.len)
|
||||||
|
: std::string(""));
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace MbedTLSPKI
|
||||||
|
} // namespace openvpn
|
@ -51,6 +51,7 @@
|
|||||||
#include <openvpn/ssl/ssllog.hpp>
|
#include <openvpn/ssl/ssllog.hpp>
|
||||||
|
|
||||||
#include <openvpn/mbedtls/pki/x509cert.hpp>
|
#include <openvpn/mbedtls/pki/x509cert.hpp>
|
||||||
|
#include <openvpn/mbedtls/pki/x509certinfo.hpp>
|
||||||
#include <openvpn/mbedtls/pki/x509crl.hpp>
|
#include <openvpn/mbedtls/pki/x509crl.hpp>
|
||||||
#include <openvpn/mbedtls/pki/dh.hpp>
|
#include <openvpn/mbedtls/pki/dh.hpp>
|
||||||
#include <openvpn/mbedtls/pki/pkctx.hpp>
|
#include <openvpn/mbedtls/pki/pkctx.hpp>
|
||||||
@ -1140,55 +1141,6 @@ namespace openvpn {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try to return the x509 subject formatted like the OpenSSL X509_NAME_oneline method.
|
|
||||||
// Only attributes matched in the switch statements below will be rendered. All other
|
|
||||||
// attributes will be ignored.
|
|
||||||
static std::string x509_get_subject(const mbedtls_x509_crt *cert)
|
|
||||||
{
|
|
||||||
std::string ret;
|
|
||||||
for (const mbedtls_x509_name *name = &cert->subject; name != nullptr; name = name->next)
|
|
||||||
{
|
|
||||||
const char *key = nullptr;
|
|
||||||
if (!MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &name->oid))
|
|
||||||
key = "CN";
|
|
||||||
else if (!MBEDTLS_OID_CMP(MBEDTLS_OID_AT_COUNTRY, &name->oid))
|
|
||||||
key = "C";
|
|
||||||
else if (!MBEDTLS_OID_CMP(MBEDTLS_OID_AT_LOCALITY, &name->oid))
|
|
||||||
key = "L";
|
|
||||||
else if (!MBEDTLS_OID_CMP(MBEDTLS_OID_AT_STATE, &name->oid))
|
|
||||||
key = "ST";
|
|
||||||
else if (!MBEDTLS_OID_CMP(MBEDTLS_OID_AT_ORGANIZATION, &name->oid))
|
|
||||||
key = "O";
|
|
||||||
else if (!MBEDTLS_OID_CMP(MBEDTLS_OID_AT_ORG_UNIT, &name->oid))
|
|
||||||
key = "OU";
|
|
||||||
else if (!MBEDTLS_OID_CMP(MBEDTLS_OID_PKCS9_EMAIL, &name->oid))
|
|
||||||
key = "emailAddress";
|
|
||||||
|
|
||||||
// make sure that key is defined and value has no embedded nulls
|
|
||||||
if (key && !string::embedded_null((const char *)name->val.p, name->val.len))
|
|
||||||
ret += "/" + std::string(key) + "=" + std::string((const char *)name->val.p, name->val.len);
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string x509_get_common_name(const mbedtls_x509_crt *cert)
|
|
||||||
{
|
|
||||||
const mbedtls_x509_name *name = &cert->subject;
|
|
||||||
|
|
||||||
// find common name
|
|
||||||
while (name != nullptr)
|
|
||||||
{
|
|
||||||
if (!MBEDTLS_OID_CMP(MBEDTLS_OID_AT_CN, &name->oid))
|
|
||||||
break;
|
|
||||||
name = name->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name)
|
|
||||||
return std::string((const char *)name->val.p, name->val.len);
|
|
||||||
else
|
|
||||||
return std::string("");
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string status_string(const mbedtls_x509_crt *cert, const int depth, const uint32_t *flags)
|
static std::string status_string(const mbedtls_x509_crt *cert, const int depth, const uint32_t *flags)
|
||||||
{
|
{
|
||||||
std::ostringstream os;
|
std::ostringstream os;
|
||||||
@ -1246,8 +1198,8 @@ namespace openvpn {
|
|||||||
// verify tls-remote
|
// verify tls-remote
|
||||||
if (!self->config->tls_remote.empty())
|
if (!self->config->tls_remote.empty())
|
||||||
{
|
{
|
||||||
const std::string subject = TLSRemote::sanitize_x509_name(x509_get_subject(cert));
|
const std::string subject = TLSRemote::sanitize_x509_name(MbedTLSPKI::x509_get_subject(cert));
|
||||||
const std::string common_name = TLSRemote::sanitize_common_name(x509_get_common_name(cert));
|
const std::string common_name = TLSRemote::sanitize_common_name(MbedTLSPKI::x509_get_common_name(cert));
|
||||||
TLSRemote::log(self->config->tls_remote, subject, common_name);
|
TLSRemote::log(self->config->tls_remote, subject, common_name);
|
||||||
if (!TLSRemote::test(self->config->tls_remote, subject, common_name))
|
if (!TLSRemote::test(self->config->tls_remote, subject, common_name))
|
||||||
{
|
{
|
||||||
@ -1317,7 +1269,7 @@ namespace openvpn {
|
|||||||
if (ssl->authcert)
|
if (ssl->authcert)
|
||||||
{
|
{
|
||||||
// save the Common Name
|
// save the Common Name
|
||||||
ssl->authcert->cn = x509_get_common_name(cert);
|
ssl->authcert->cn = MbedTLSPKI::x509_get_common_name(cert);
|
||||||
|
|
||||||
// save the leaf cert serial number
|
// save the leaf cert serial number
|
||||||
const mbedtls_x509_buf *s = &cert->serial;
|
const mbedtls_x509_buf *s = &cert->serial;
|
||||||
|
Loading…
Reference in New Issue
Block a user