tizen beta release
[framework/web/wrt-commons.git] / modules / vcore / src / vcore / OCSPCertMgrUtil.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  * @author      Michal Ciepielski(m.ciepielski@samsung.com)
18  * @version     0.3
19  * @brief
20  */
21
22 #include "OCSPCertMgrUtil.h"
23 #include "SSLContainers.h"
24
25 #include <openssl/pem.h>
26 #include <openssl/ocsp.h>
27 #include <dpl/log/log.h>
28 #include <dpl/scoped_resource.h>
29 #include <string.h>
30 #include <iostream>
31 #include <string>
32
33 #include <cert-service.h>
34
35 namespace {
36 const int MAX_BUF = 1024;
37
38 struct ContextDeleter
39 {
40     typedef CERT_CONTEXT* Type;
41     static Type NullValue()
42     {
43         return NULL;
44     }
45     static void Destroy(Type context)
46     {
47         if (context) {
48             cert_svc_cert_context_final(context);
49         }
50     }
51 };
52 }
53
54 namespace ValidationCore {
55 namespace OCSPCertMgrUtil {
56 /*
57  * TODO This API function should be changed to:
58  * CertifiatePtr getCertFromStore(const std::string &subject);
59  *
60  * All of cert_svc function could return error because input
61  * data are corruped. That's why I dont want to throw exceptions
62  * in this function.
63  */
64 void getCertFromStore(X509_NAME *subject,
65         X509 **xcert)
66 {
67     if (!xcert || *xcert || !subject) {
68         LogError("Invalid input!");
69         return;
70     }
71
72     typedef DPL::ScopedResource<ContextDeleter> ScopedContext;
73
74     int result;
75     char buffer[MAX_BUF];
76     const unsigned char* ptr = NULL;
77     X509 *pCertificate = NULL;
78     cert_svc_filename_list *fileList = NULL;
79
80     X509_NAME_oneline(subject, buffer, MAX_BUF);
81
82     ScopedContext ctx(cert_svc_cert_context_init());
83     if (ctx.Get() == NULL) {
84         LogWarning("Error in cert_svc_cert_context_init.");
85         return;
86     }
87
88     LogDebug("Search certificate with subject: " << buffer);
89     result = cert_svc_search_certificate(ctx.Get(), SUBJECT_STR, buffer);
90     LogDebug("Search finished!");
91
92     if (CERT_SVC_ERR_NO_ERROR != result) {
93         LogWarning("Error during certificate search");
94         return;
95     }
96
97     fileList = ctx.Get()->fileNames;
98
99     if (fileList == NULL) {
100         LogDebug("No certificate found");
101         return;
102     }
103
104     if (fileList->filename == NULL) {
105         LogWarning("Empty filename");
106         return;
107     }
108
109     LogDebug("Found cert file: " << fileList->filename);
110     ScopedContext ctx2(cert_svc_cert_context_init());
111
112     if (ctx2.Get() == NULL) {
113         LogWarning("Error in cert_svc_cert_context_init.");
114         return;
115     }
116
117     // TODO add read_certifcate_from_file function to Certificate.h
118     if (CERT_SVC_ERR_NO_ERROR !=
119         cert_svc_load_file_to_context(ctx2.Get(), fileList->filename)) {
120         LogWarning("Error in cert_svc_load_file_to_context");
121         return;
122     }
123
124     ptr = ctx2.Get()->certBuf->data;
125     // create a certificate from mem buff
126     pCertificate = d2i_X509(NULL, &ptr, ctx2.Get()->certBuf->size);
127
128     if (pCertificate == NULL) {
129         LogWarning("Error during certificate conversion in d2i_X509");
130         return;
131     }
132
133     *xcert = pCertificate;
134     if (fileList->next != NULL) {
135         LogError("There is more then one certificate with same subject :/");
136         // TODO Implement me.
137         for (fileList = fileList->next;
138              fileList != NULL;
139              fileList = fileList->next) {
140             LogError(
141                 "Additional certificate with same subject: " <<
142                 fileList->filename);
143         }
144     }
145 }
146
147 CertificatePtr getParentFromStore(const CertificatePtr &certificate)
148 {
149     Assert(certificate.Get());
150     X509* rawPtr = certificate->getX509();
151
152     /* TODO Add getIssuerName function to Certificate.h */
153     X509_NAME *name = X509_get_issuer_name(rawPtr);
154
155     X509* rawTemp = NULL;
156     getCertFromStore(name, &rawTemp);
157
158     if (rawTemp == NULL) {
159         return CertificatePtr();
160     }
161
162     SSLSmartContainer<X509> scope(rawTemp);
163     return CertificatePtr(new Certificate(rawTemp));
164 }
165
166 CertificateList completeCertificateChain(const CertificateList &certificateList)
167 {
168     CertificateList result = certificateList;
169     CertificatePtr last = result.back();
170     if (last->isSignedBy(last)) {
171         return result;
172     }
173     CertificatePtr parent = getParentFromStore(last);
174     if (parent.Get()) {
175         result.push_back(parent);
176     }
177     return result;
178 }
179 } // namespace OCSPCertMgrUtil
180 } // namespace ValidationCore