than ECRYPT).
** API and ABI modifications:
+GNUTLS_VERIFY_DO_NOT_ALLOW_WILDCARDS: Added
gnutls_privkey_generate: Added
gnutls_pkcs11_crt_is_known: Added
gnutls_fips140_mode_enabled: Added
gnutls_privkey_import_dsa_raw: Added
gnutls_privkey_import_rsa_raw: Added
gnutls_privkey_verify_params: Added
+gnutls_x509_crt_check_hostname2: Added
+gnutls_openpgp_crt_check_hostname2: Added
gnutls_x509_name_constraints_init: Added
gnutls_x509_name_constraints_deinit: Added
gnutls_x509_crt_get_name_constraints: Added
cert_auth_info_t info;
gnutls_certificate_credentials_t cred;
int peer_certificate_list_size, ret;
+ unsigned int verify_flags;
CHECK_AUTH(GNUTLS_CRD_CERTIFICATE, GNUTLS_E_INVALID_REQUEST);
return GNUTLS_E_NO_CERTIFICATE_FOUND;
}
+ verify_flags = cred->verify_flags | session->internals.priorities.additional_verify_flags;
+
/* generate a list of gnutls_certs based on the auth info
* raw certs.
*/
ret =
_gnutls_openpgp_verify_key(cred, hostname,
&info->raw_certificate_list[0],
- peer_certificate_list_size, status);
+ peer_certificate_list_size,
+ verify_flags,
+ status);
if (ret < 0) {
gnutls_assert();
* values or zero if the certificate is trusted. Note that value in @status
* is set only when the return value of this function is success (i.e, failure
* to trust a certificate does not imply a negative return value).
+ * The default verification flags used by this function can be overriden
+ * using gnutls_certificate_set_verify_flags().
*
* If available the OCSP Certificate Status extension will be
* utilized by this function.
* values or zero if the certificate is trusted. Note that value in @status
* is set only when the return value of this function is success (i.e, failure
* to trust a certificate does not imply a negative return value).
+ * The default verification flags used by this function can be overriden
+ * using gnutls_certificate_set_verify_flags().
*
* If the @hostname provided is non-NULL then this function will compare
* the hostname in the certificate against the given. The comparison will
*/
int
_gnutls_hostname_compare(const char *certname,
- size_t certnamesize, const char *hostname)
+ size_t certnamesize, const char *hostname, unsigned vflags)
{
char *p;
unsigned i;
return hostname_compare_raw(certname, certnamesize, hostname);
}
- if (*certname == '*') {
+ if (*certname == '*' && !(vflags & GNUTLS_VERIFY_DO_NOT_ALLOW_WILDCARDS)) {
/* a wildcard certificate */
/* ensure that we have at least two domain components after
certnamesize--;
while (1) {
- /* Use a recursive call to allow multiple wildcards */
if (hostname_compare_ascii(certname, certnamesize, hostname))
return 1;
uint8_t * bin_data, size_t * bin_size);
int _gnutls_hostname_compare(const char *certname, size_t certnamesize,
- const char *hostname);
+ const char *hostname, unsigned vflags);
#define MAX_CN 256
#define MAX_DN 1024
if (hostname) {
ret =
- gnutls_x509_crt_check_hostname(peer_certificate_list
- [0], hostname);
+ gnutls_x509_crt_check_hostname2(peer_certificate_list
+ [0], hostname, verify_flags);
if (ret == 0)
*status |= GNUTLS_CERT_UNEXPECTED_OWNER|GNUTLS_CERT_INVALID;
}
int gnutls_openpgp_crt_check_hostname(gnutls_openpgp_crt_t key,
const char *hostname);
+int gnutls_openpgp_crt_check_hostname2(gnutls_openpgp_crt_t key,
+ const char *hostname, unsigned int flags);
int gnutls_openpgp_crt_get_revoked_status(gnutls_openpgp_crt_t key);
size_t * buf_size);
int gnutls_x509_crt_check_hostname(gnutls_x509_crt_t cert,
const char *hostname);
+int gnutls_x509_crt_check_hostname2(gnutls_x509_crt_t cert,
+ const char *hostname, unsigned int flags);
int gnutls_x509_crt_get_signature_algorithm(gnutls_x509_crt_t cert);
int gnutls_x509_crt_get_signature(gnutls_x509_crt_t cert,
* this unless you understand the security implications.
* @GNUTLS_VERIFY_DISABLE_CRL_CHECKS: Disable checking for validity
* using certificate revocation lists or the available OCSP data.
+ * @GNUTLS_VERIFY_DO_NOT_ALLOW_WILDCARDS: When including a hostname
+ * check in the verification, do not consider any wildcards.
*
* Enumeration of different certificate verify flags. Additional
* verification profiles can be set using GNUTLS_PROFILE_TO_VFLAGS()
GNUTLS_VERIFY_DISABLE_CRL_CHECKS = 1 << 9,
GNUTLS_VERIFY_ALLOW_UNSORTED_CHAIN = 1 << 10,
GNUTLS_VERIFY_DO_NOT_ALLOW_UNSORTED_CHAIN = 1 << 11,
+ GNUTLS_VERIFY_DO_NOT_ALLOW_WILDCARDS = 1 << 12,
} gnutls_certificate_verify_flags;
/**
gnutls_x509_key_purpose_get;
gnutls_x509_ext_import_key_purposes;
gnutls_x509_ext_export_key_purposes;
+ gnutls_x509_crt_check_hostname2;
+ gnutls_openpgp_crt_check_hostname2;
} GNUTLS_3_0_0;
GNUTLS_PRIVATE {
_gnutls_openpgp_verify_key(const gnutls_certificate_credentials_t cred,
const char *hostname,
const gnutls_datum_t * cert_list,
- int cert_list_length, unsigned int *status)
+ int cert_list_length,
+ unsigned int verify_flags,
+ unsigned int *status)
{
int ret = 0;
gnutls_openpgp_crt_t key = NULL;
*status |= GNUTLS_CERT_SIGNER_NOT_FOUND;
if (hostname) {
- ret = gnutls_openpgp_crt_check_hostname(key, hostname);
+ ret = gnutls_openpgp_crt_check_hostname2(key, hostname, verify_flags);
if (ret == 0)
*status |= GNUTLS_CERT_UNEXPECTED_OWNER;
}
int _gnutls_openpgp_verify_key(const gnutls_certificate_credentials_t,
const char *hostname,
const gnutls_datum_t * cert_list,
- int cert_list_length, unsigned int *status);
+ int cert_list_length,
+ unsigned int verify_flags,
+ unsigned int *status);
int _gnutls_openpgp_fingerprint(const gnutls_datum_t * cert,
unsigned char *fpr, size_t * fprlen);
time_t _gnutls_openpgp_get_raw_key_creation_time(const gnutls_datum_t *
int
gnutls_openpgp_crt_check_hostname(gnutls_openpgp_crt_t key,
const char *hostname)
+{
+ return gnutls_openpgp_crt_check_hostname2(key, hostname, 0);
+}
+
+/**
+ * gnutls_openpgp_crt_check_hostname2:
+ * @key: should contain a #gnutls_openpgp_crt_t structure
+ * @hostname: A null terminated string that contains a DNS name
+ * @flags: gnutls_certificate_verify_flags
+ *
+ * This function will check if the given key's owner matches the
+ * given hostname.
+ *
+ * Unless, the flag %GNUTLS_VERIFY_DO_NOT_ALLOW_WILDCARDS is specified,
+ * wildcards are only considered if the domain name consists of three
+ * components or more, and the wildcard starts at the leftmost position.
+ *
+ * Returns: non-zero for a successful match, and zero on failure.
+ **/
+int
+gnutls_openpgp_crt_check_hostname2(gnutls_openpgp_crt_t key,
+ const char *hostname, unsigned flags)
{
char dnsname[MAX_CN];
size_t dnsnamesize;
dnsnamesize--;
if (_gnutls_hostname_compare
- (dnsname, dnsnamesize, hostname))
+ (dnsname, dnsnamesize, hostname, flags))
return 1;
}
}
gnutls_x509_crt_check_hostname(gnutls_x509_crt_t cert,
const char *hostname)
{
+ return gnutls_x509_crt_check_hostname2(cert, hostname, 0);
+}
+
+/**
+ * gnutls_x509_crt_check_hostname:
+ * @cert: should contain an gnutls_x509_crt_t structure
+ * @hostname: A null terminated string that contains a DNS name
+ * @flags: gnutls_certificate_verify_flags
+ *
+ * This function will check if the given certificate's subject matches
+ * the given hostname. This is a basic implementation of the matching
+ * described in RFC2818 (HTTPS), which takes into account wildcards,
+ * and the DNSName/IPAddress subject alternative name PKIX extension.
+ *
+ * The comparison may have false-negatives as it is done byte by byte in
+ * non-ascii names.
+ *
+ * Unless, the flag %GNUTLS_VERIFY_DO_NOT_ALLOW_WILDCARDS is specified,
+ * wildcards are only considered if the domain name consists of three
+ * components or more, and the wildcard starts at the leftmost position.
+ *
+ * Returns: non-zero for a successful match, and zero on failure.
+ **/
+int
+gnutls_x509_crt_check_hostname2(gnutls_x509_crt_t cert,
+ const char *hostname, unsigned int flags)
+{
char dnsname[MAX_CN];
size_t dnsnamesize;
if (ret == GNUTLS_SAN_DNSNAME) {
found_dnsname = 1;
if (_gnutls_hostname_compare
- (dnsname, dnsnamesize, hostname)) {
+ (dnsname, dnsnamesize, hostname, flags)) {
return 1;
}
}
}
if (_gnutls_hostname_compare
- (dnsname, dnsnamesize, hostname)) {
+ (dnsname, dnsnamesize, hostname, flags)) {
return 1;
}
}
if (!ret)
fail("%d: Hostname incorrectly does not match (%d)\n", __LINE__, ret);
+ ret = gnutls_x509_crt_check_hostname2(x509, "www.example.org", GNUTLS_VERIFY_DO_NOT_ALLOW_WILDCARDS);
+ if (ret)
+ fail("%d: Hostname incorrectly matches (%d)\n", __LINE__, ret);
+
ret = gnutls_x509_crt_check_hostname(x509, "foo.example.org");
if (!ret)
fail("%d: Hostname incorrectly does not match (%d)\n", __LINE__, ret);