Updated through tag hostap_2_5 from git://w1.fi/hostap.git
[mech_eap.git] / libeap / src / tls / x509v3.c
index bc93df6..b51dfcd 100644 (file)
@@ -1,15 +1,9 @@
 /*
  * X.509v3 certificate parsing and processing (RFC 3280 profile)
- * Copyright (c) 2006-2007, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2006-2011, Jouni Malinen <j@w1.fi>
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
+ * This software may be distributed under the terms of the BSD license.
+ * See README for more details.
  */
 
 #include "includes.h"
@@ -449,17 +443,16 @@ static int x509_parse_name(const u8 *buf, size_t len, struct x509_name *name,
                        return -1;
                }
 
-               val = os_malloc(hdr.length + 1);
+               val = dup_binstr(hdr.payload, hdr.length);
                if (val == NULL) {
                        x509_free_name(name);
                        return -1;
                }
-               os_memcpy(val, hdr.payload, hdr.length);
-               val[hdr.length] = '\0';
                if (os_strlen(val) != hdr.length) {
                        wpa_printf(MSG_INFO, "X509: Reject certificate with "
                                   "embedded NUL byte in a string (%s[NUL])",
                                   val);
+                       os_free(val);
                        x509_free_name(name);
                        return -1;
                }
@@ -519,7 +512,7 @@ void x509_name_string(struct x509_name *name, char *buf, size_t len)
                ret = os_snprintf(pos, end - pos, "%s=%s, ",
                                  x509_name_attr_str(name->attr[i].type),
                                  name->attr[i].value);
-               if (ret < 0 || ret >= end - pos)
+               if (os_snprintf_error(end - pos, ret))
                        goto done;
                pos += ret;
        }
@@ -534,7 +527,7 @@ void x509_name_string(struct x509_name *name, char *buf, size_t len)
        if (name->email) {
                ret = os_snprintf(pos, end - pos, "/emailAddress=%s",
                                  name->email);
-               if (ret < 0 || ret >= end - pos)
+               if (os_snprintf_error(end - pos, ret))
                        goto done;
                pos += ret;
        }
@@ -1355,7 +1348,8 @@ static int x509_parse_tbs_certificate(const u8 *buf, size_t len,
                wpa_printf(MSG_DEBUG, "X509: issuerUniqueID");
                /* TODO: parse UniqueIdentifier ::= BIT STRING */
 
-               if (hdr.payload + hdr.length == end)
+               pos = hdr.payload + hdr.length;
+               if (pos == end)
                        return 0;
 
                if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
@@ -1373,7 +1367,8 @@ static int x509_parse_tbs_certificate(const u8 *buf, size_t len,
                wpa_printf(MSG_DEBUG, "X509: subjectUniqueID");
                /* TODO: parse UniqueIdentifier ::= BIT STRING */
 
-               if (hdr.payload + hdr.length == end)
+               pos = hdr.payload + hdr.length;
+               if (pos == end)
                        return 0;
 
                if (asn1_get_next(pos, end - pos, &hdr) < 0 ||
@@ -1516,7 +1511,7 @@ struct x509_certificate * x509_certificate_parse(const u8 *buf, size_t len)
        if (pos + hdr.length < end) {
                wpa_hexdump(MSG_MSGDUMP, "X509: Ignoring extra data after DER "
                            "encoded certificate",
-                           pos + hdr.length, end - pos + hdr.length);
+                           pos + hdr.length, end - (pos + hdr.length));
                end = pos + hdr.length;
        }
 
@@ -1781,13 +1776,22 @@ skip_digest_oid:
        }
 
        if (hdr.length != hash_len ||
-           os_memcmp(hdr.payload, hash, hdr.length) != 0) {
+           os_memcmp_const(hdr.payload, hash, hdr.length) != 0) {
                wpa_printf(MSG_INFO, "X509: Certificate Digest does not match "
                           "with calculated tbsCertificate hash");
                os_free(data);
                return -1;
        }
 
+       if (hdr.payload + hdr.length < data + data_len) {
+               wpa_hexdump(MSG_INFO,
+                           "X509: Extra data after certificate signature hash",
+                           hdr.payload + hdr.length,
+                           data + data_len - hdr.payload - hdr.length);
+               os_free(data);
+               return -1;
+       }
+
        os_free(data);
 
        wpa_printf(MSG_DEBUG, "X509: Certificate Digest matches with "
@@ -1834,7 +1838,7 @@ static int x509_valid_issuer(const struct x509_certificate *cert)
  */
 int x509_certificate_chain_validate(struct x509_certificate *trusted,
                                    struct x509_certificate *chain,
-                                   int *reason)
+                                   int *reason, int disable_time_checks)
 {
        long unsigned idx;
        int chain_trusted = 0;
@@ -1854,10 +1858,11 @@ int x509_certificate_chain_validate(struct x509_certificate *trusted,
                if (chain_trusted)
                        continue;
 
-               if ((unsigned long) now.sec <
-                   (unsigned long) cert->not_before ||
-                   (unsigned long) now.sec >
-                   (unsigned long) cert->not_after) {
+               if (!disable_time_checks &&
+                   ((unsigned long) now.sec <
+                    (unsigned long) cert->not_before ||
+                    (unsigned long) now.sec >
+                    (unsigned long) cert->not_after)) {
                        wpa_printf(MSG_INFO, "X509: Certificate not valid "
                                   "(now=%lu not_before=%lu not_after=%lu)",
                                   now.sec, cert->not_before, cert->not_after);