1// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/base/x509_cert_types.h"
6
7#include "net/base/x509_certificate.h"
8#include "base/logging.h"
9#include "base/string_number_conversions.h"
10#include "base/string_piece.h"
11#include "base/time.h"
12
13namespace net {
14
15namespace {
16
17// Helper for ParseCertificateDate. |*field| must contain at least
18// |field_len| characters. |*field| will be advanced by |field_len| on exit.
19// |*ok| is set to false if there is an error in parsing the number, but left
20// untouched otherwise. Returns the parsed integer.
21int ParseIntAndAdvance(const char** field, size_t field_len, bool* ok) {
22  int result = 0;
23  *ok &= base::StringToInt(*field, *field + field_len, &result);
24  *field += field_len;
25  return result;
26}
27
28}  // namespace
29
30CertPrincipal::CertPrincipal() {
31}
32
33CertPrincipal::CertPrincipal(const std::string& name) : common_name(name) {}
34
35CertPrincipal::~CertPrincipal() {
36}
37
38std::string CertPrincipal::GetDisplayName() const {
39  if (!common_name.empty())
40    return common_name;
41  if (!organization_names.empty())
42    return organization_names[0];
43  if (!organization_unit_names.empty())
44    return organization_unit_names[0];
45
46  return std::string();
47}
48
49CertPolicy::CertPolicy() {
50}
51
52CertPolicy::~CertPolicy() {
53}
54
55CertPolicy::Judgment CertPolicy::Check(
56    X509Certificate* cert) const {
57  // It shouldn't matter which set we check first, but we check denied first
58  // in case something strange has happened.
59
60  if (denied_.find(cert->fingerprint()) != denied_.end()) {
61    // DCHECK that the order didn't matter.
62    DCHECK(allowed_.find(cert->fingerprint()) == allowed_.end());
63    return DENIED;
64  }
65
66  if (allowed_.find(cert->fingerprint()) != allowed_.end()) {
67    // DCHECK that the order didn't matter.
68    DCHECK(denied_.find(cert->fingerprint()) == denied_.end());
69    return ALLOWED;
70  }
71
72  // We don't have a policy for this cert.
73  return UNKNOWN;
74}
75
76void CertPolicy::Allow(X509Certificate* cert) {
77  // Put the cert in the allowed set and (maybe) remove it from the denied set.
78  denied_.erase(cert->fingerprint());
79  allowed_.insert(cert->fingerprint());
80}
81
82void CertPolicy::Deny(X509Certificate* cert) {
83  // Put the cert in the denied set and (maybe) remove it from the allowed set.
84  allowed_.erase(cert->fingerprint());
85  denied_.insert(cert->fingerprint());
86}
87
88bool CertPolicy::HasAllowedCert() const {
89  return !allowed_.empty();
90}
91
92bool CertPolicy::HasDeniedCert() const {
93  return !denied_.empty();
94}
95
96bool ParseCertificateDate(const base::StringPiece& raw_date,
97                          CertDateFormat format,
98                          base::Time* time) {
99  size_t year_length = format == CERT_DATE_FORMAT_UTC_TIME ? 2 : 4;
100
101  if (raw_date.length() < 11 + year_length)
102    return false;
103
104  const char* field = raw_date.data();
105  bool valid = true;
106  base::Time::Exploded exploded = {0};
107
108  exploded.year =         ParseIntAndAdvance(&field, year_length, &valid);
109  exploded.month =        ParseIntAndAdvance(&field, 2, &valid);
110  exploded.day_of_month = ParseIntAndAdvance(&field, 2, &valid);
111  exploded.hour =         ParseIntAndAdvance(&field, 2, &valid);
112  exploded.minute =       ParseIntAndAdvance(&field, 2, &valid);
113  exploded.second =       ParseIntAndAdvance(&field, 2, &valid);
114  if (valid && year_length == 2)
115    exploded.year += exploded.year < 50 ? 2000 : 1900;
116
117  valid &= exploded.HasValidValues();
118
119  if (!valid)
120    return false;
121
122  *time = base::Time::FromUTCExploded(exploded);
123  return true;
124}
125
126}  // namespace net
127