Tizen 2.1 base
[framework/web/wrt-commons.git] / modules / vcore / src / vcore / CachedOCSP.cpp
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 /**
17  *
18  * @file       CachedOCSP.cpp
19  * @author     Tomasz Swierczek (t.swierczek@samsung.com)
20  * @version    0.1
21  * @brief      Cached OCSP class implementation
22  */
23
24 #include <string>
25 #include <time.h>
26
27 #include <dpl/foreach.h>
28 #include <dpl/log/log.h>
29 #include <dpl/foreach.h>
30
31 #include "OCSP.h"
32 #include "CachedOCSP.h"
33 #include "Certificate.h"
34 #include "CertificateCacheDAO.h"
35
36 namespace ValidationCore {
37
38 const time_t CachedOCSP::OCSP_minTimeValid = 3600;      // one hour in seconds
39
40 const time_t CachedOCSP::OCSP_maxTimeValid =
41         3600 * 24 * 7;                                  // one week in seconds
42
43 const time_t CachedOCSP::OCSP_refreshBefore = 3600;     // one hour in seconds
44
45 VerificationStatus CachedOCSP::check(const CertificateCollection &certs)
46 {
47     OCSPCachedStatus db_status;
48     time_t now;
49     time(&now);
50
51     db_status.cert_chain = certs.toBase64String();
52     db_status.end_entity_check = false;
53
54     if (CertificateCacheDAO::getOCSPStatus(&db_status)) {
55         LogDebug("Found cache entry for OCSP");
56         if (now < db_status.next_update_time) {
57             LogDebug("Cache response valid");
58             return db_status.ocsp_status;
59         }
60     }
61
62     // here we need to get OCSP result and add/update cache
63     OCSP ocsp;
64     CertificateList list = certs.getChain();
65     ocsp.setTrustedStore(list);
66
67     VerificationStatusSet statusSet = ocsp.validateCertificateList(list);
68     db_status.ocsp_status = statusSet.convertToStatus();
69     db_status.next_update_time = ocsp.getResponseValidity();
70     CertificateCacheDAO::setOCSPStatus(db_status.cert_chain,
71                                        db_status.ocsp_status,
72                                        db_status.end_entity_check,
73                                        getNextUpdateTime(
74                                            now,
75                                            db_status.next_update_time));
76     return db_status.ocsp_status;
77 }
78
79 VerificationStatus CachedOCSP::checkEndEntity(CertificateCollection &certs)
80 {
81     OCSPCachedStatus db_status;
82     time_t now;
83     time(&now);
84
85     db_status.cert_chain = certs.toBase64String();
86     db_status.end_entity_check = true;
87
88     if (CertificateCacheDAO::getOCSPStatus(&db_status)) {
89         LogDebug("Found cache entry for OCSP");
90         if (now < db_status.next_update_time) {
91             LogDebug("Cache response valid");
92             return db_status.ocsp_status;
93         }
94     }
95
96     // here we need to send request via OCSP and add/update cache
97     CertificateList clst;
98     getCertsForEndEntity(certs, &clst);
99
100     OCSP ocsp;
101     ocsp.setTrustedStore(certs.getCertificateList());
102
103     const char *defResponderURI = getenv(OCSP::DEFAULT_RESPONDER_URI_ENV);
104
105     if (defResponderURI) {
106         ocsp.setUseDefaultResponder(true);
107         ocsp.setDefaultResponder(defResponderURI);
108     }
109
110     VerificationStatusSet statusSet = ocsp.validateCertificateList(clst);
111     db_status.ocsp_status = statusSet.convertToStatus();
112     db_status.next_update_time = ocsp.getResponseValidity();
113
114     CertificateCacheDAO::setOCSPStatus(db_status.cert_chain,
115                                        db_status.ocsp_status,
116                                        db_status.end_entity_check,
117                                        getNextUpdateTime(
118                                            now,
119                                            db_status.next_update_time));
120
121     return db_status.ocsp_status;
122 }
123
124 void CachedOCSP::updateCache()
125 {
126     time_t now;
127     time(&now);
128     now += OCSP_refreshBefore;
129     OCSPCachedStatusList list;
130     CertificateCacheDAO::getOCSPStatusList(&list);
131     FOREACH(db_status, list) {
132         if (now >= db_status->next_update_time) {
133             // this response needs to be refreshed
134             // TODO: check result? update even errors? need to check RFC
135             CertificateCollection col;
136             col.load(db_status->cert_chain);
137
138             OCSP ocsp;
139             CertificateList chain = col.getChain();
140             ocsp.setTrustedStore(chain);
141
142             VerificationStatusSet statusSet;
143
144             if (db_status->end_entity_check) {
145                 CertificateList clst;
146                 getCertsForEndEntity(col, &clst);
147                 statusSet = ocsp.validateCertificateList(clst);
148             } else {
149                 statusSet = ocsp.validateCertificateList(chain);
150             }
151
152             db_status->ocsp_status = statusSet.convertToStatus();
153             db_status->next_update_time = ocsp.getResponseValidity();
154
155             CertificateCacheDAO::setOCSPStatus(db_status->cert_chain,
156                                                db_status->ocsp_status,
157                                                db_status->end_entity_check,
158                                                db_status->next_update_time);
159         }
160     }
161 }
162
163 void CachedOCSP::getCertsForEndEntity(
164         const CertificateCollection &certs, CertificateList* clst)
165 {
166     if (NULL == clst) {
167         LogError("NULL pointer");
168         return;
169     }
170
171     if (certs.isChain() && certs.size() >= 2) {
172         CertificateList::const_iterator icert = certs.begin();
173         clst->push_back(*icert);
174         ++icert;
175         clst->push_back(*icert);
176     }
177 }
178
179 time_t CachedOCSP::getNextUpdateTime(time_t now, time_t response_validity)
180 {
181     long min = now + OCSP_minTimeValid;
182     long max = now + OCSP_maxTimeValid;
183     if (response_validity < min) {
184         return min;
185     }
186     if (response_validity > max) {
187         return max;
188     }
189     return response_validity;
190 }
191
192 } // namespace ValidationCore