00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "openSSLWrapper.h"
00016
00017 #ifdef HAVE_OPENSSL
00018
00019 #include "virtualFileSystem.h"
00020 #include "ca_bundle_data_src.c"
00021
00022 OpenSSLWrapper *OpenSSLWrapper::_global_ptr = NULL;
00023
00024
00025
00026
00027
00028
00029 OpenSSLWrapper::
00030 OpenSSLWrapper() {
00031
00032
00033
00034
00035 SSL_library_init();
00036
00037 OpenSSL_add_all_algorithms();
00038
00039 _x509_store = X509_STORE_new();
00040 X509_STORE_set_default_paths(_x509_store);
00041
00042
00043
00044 load_certificates_from_der_ram((const char *)ca_bundle_data, ca_bundle_data_len);
00045
00046
00047 ConfigVariableFilename ca_bundle_filename
00048 ("ca-bundle-filename", "",
00049 PRC_DESC("This names the certificate authority file for OpenSSL "
00050 "to use to verify whether SSL certificates are trusted or not. "
00051 "The file named by this setting should contain one or more "
00052 "PEM-formatted certificates from trusted certificate "
00053 "authorities. This is a fairly standard file; a copy of "
00054 "ca-bundle.crt is included in the OpenSSL distribution, and "
00055 "is also included with Panda."));
00056
00057 if (!ca_bundle_filename.empty()) {
00058 load_certificates(ca_bundle_filename);
00059 }
00060
00061 ConfigVariableList ssl_certificates
00062 ("ssl-certificates",
00063 PRC_DESC("This variable lists additional filenames, on top of the file "
00064 "named by ca-bundle-filename, that contain trusted SSL "
00065 "certificates or certificate authorities."));
00066
00067 int num_certs = ssl_certificates.get_num_unique_values();
00068 for (int ci = 0; ci < num_certs; ci++) {
00069 string cert_file = ssl_certificates.get_unique_value(ci);
00070 Filename filename = Filename::expand_from(cert_file);
00071 load_certificates(filename);
00072 }
00073 }
00074
00075
00076
00077
00078
00079
00080 OpenSSLWrapper::
00081 ~OpenSSLWrapper() {
00082
00083 X509_STORE_free(_x509_store);
00084 }
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094 void OpenSSLWrapper::
00095 clear_certificates() {
00096
00097 X509_STORE_free(_x509_store);
00098 _x509_store = X509_STORE_new();
00099
00100
00101
00102 }
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120 int OpenSSLWrapper::
00121 load_certificates(const Filename &filename) {
00122 VirtualFileSystem *vfs = VirtualFileSystem::get_global_ptr();
00123
00124
00125 string data;
00126 if (!vfs->read_file(filename, data, true)) {
00127
00128 express_cat.info()
00129 << "Could not read " << filename << ".\n";
00130 return 0;
00131 }
00132
00133 int result = load_certificates_from_pem_ram(data.data(), data.size());
00134
00135 if (result <= 0) {
00136 express_cat.info()
00137 << "Could not load certificates from " << filename << ".\n";
00138 notify_ssl_errors();
00139 return 0;
00140 }
00141
00142 if (express_cat.is_debug()) {
00143 express_cat.debug()
00144 << "Appending " << result << " SSL certificates from "
00145 << filename << "\n";
00146 }
00147
00148 return result;
00149 }
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164 int OpenSSLWrapper::
00165 load_certificates_from_pem_ram(const char *data, size_t data_size) {
00166 STACK_OF(X509_INFO) *inf;
00167
00168
00169
00170
00171 BIO *mbio = BIO_new_mem_buf((void *)data, data_size);
00172
00173
00174
00175 ERR_clear_error();
00176 inf = PEM_X509_INFO_read_bio(mbio, NULL, NULL, NULL);
00177 BIO_free(mbio);
00178
00179 if (!inf) {
00180
00181 express_cat.info()
00182 << "PEM_X509_INFO_read_bio() returned NULL.\n";
00183 notify_ssl_errors();
00184 return 0;
00185 }
00186
00187 if (express_cat.is_spam()) {
00188 express_cat.spam()
00189 << "PEM_X509_INFO_read_bio() found " << sk_X509_INFO_num(inf)
00190 << " entries.\n";
00191 }
00192
00193
00194
00195 int count = 0;
00196 int num_entries = sk_X509_INFO_num(inf);
00197 for (int i = 0; i < num_entries; i++) {
00198 X509_INFO *itmp = sk_X509_INFO_value(inf, i);
00199
00200 if (itmp->x509) {
00201 int result = X509_STORE_add_cert(_x509_store, itmp->x509);
00202 if (result == 0) {
00203 notify_debug_ssl_errors();
00204 } else {
00205 ++count;
00206 }
00207
00208 if (express_cat.is_spam()) {
00209 express_cat.spam()
00210 << "Entry " << i << " is x509\n";
00211 }
00212
00213 } else if (itmp->crl) {
00214 int result = X509_STORE_add_crl(_x509_store, itmp->crl);
00215 if (result == 0) {
00216 notify_debug_ssl_errors();
00217 } else {
00218 ++count;
00219 }
00220
00221 if (express_cat.is_spam()) {
00222 express_cat.spam()
00223 << "Entry " << i << " is crl\n";
00224 }
00225
00226 } else if (itmp->x_pkey) {
00227 if (express_cat.is_spam()) {
00228 express_cat.spam()
00229 << "Entry " << i << " is pkey\n";
00230 }
00231
00232 } else {
00233 if (express_cat.is_spam()) {
00234 express_cat.spam()
00235 << "Entry " << i << " is unknown type\n";
00236 }
00237 }
00238 }
00239 sk_X509_INFO_pop_free(inf, X509_INFO_free);
00240
00241 if (express_cat.is_spam()) {
00242 express_cat.spam()
00243 << "successfully loaded " << count << " entries.\n";
00244 }
00245
00246 return count;
00247 }
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262 int OpenSSLWrapper::
00263 load_certificates_from_der_ram(const char *data, size_t data_size) {
00264 if (express_cat.is_spam()) {
00265 express_cat.spam()
00266 << "load_certificates_from_der_ram(" << (void *)data
00267 << ", " << data_size << ")\n";
00268 }
00269
00270 int count = 0;
00271
00272 #if OPENSSL_VERSION_NUMBER >= 0x00908000L
00273
00274 const unsigned char *bp, *bp_end;
00275 #else
00276
00277 unsigned char *bp, *bp_end;
00278 #endif
00279
00280 bp = (unsigned char *)data;
00281 bp_end = bp + data_size;
00282 while (bp < bp_end) {
00283 X509 *x509 = d2i_X509(NULL, &bp, bp_end - bp);
00284 if (x509 == NULL) {
00285 notify_ssl_errors();
00286 break;
00287 }
00288
00289 int result = X509_STORE_add_cert(_x509_store, x509);
00290 if (result == 0) {
00291 notify_debug_ssl_errors();
00292 } else {
00293 ++count;
00294 }
00295 }
00296
00297
00298 if (express_cat.is_spam()) {
00299 express_cat.spam()
00300 << "loaded " << count << " certificates\n";
00301 }
00302
00303 return count;
00304 }
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318
00319 X509_STORE *OpenSSLWrapper::
00320 get_x509_store() {
00321 return _x509_store;
00322 }
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334 void OpenSSLWrapper::
00335 notify_ssl_errors() {
00336 #ifdef REPORT_OPENSSL_ERRORS
00337 static bool strings_loaded = false;
00338 if (!strings_loaded) {
00339 SSL_load_error_strings();
00340 strings_loaded = true;
00341 }
00342
00343 unsigned long e = ERR_get_error();
00344 while (e != 0) {
00345 static const size_t buffer_len = 256;
00346 char buffer[buffer_len];
00347 ERR_error_string_n(e, buffer, buffer_len);
00348 express_cat.warning() << buffer << "\n";
00349 e = ERR_get_error();
00350 }
00351 #endif // REPORT_OPENSSL_ERRORS
00352 }
00353
00354
00355
00356
00357
00358
00359
00360 void OpenSSLWrapper::
00361 notify_debug_ssl_errors() {
00362 #ifdef REPORT_OPENSSL_ERRORS
00363 static bool strings_loaded = false;
00364 if (!strings_loaded) {
00365 SSL_load_error_strings();
00366 strings_loaded = true;
00367 }
00368
00369 unsigned long e = ERR_get_error();
00370 while (e != 0) {
00371 if (express_cat.is_debug()) {
00372 static const size_t buffer_len = 256;
00373 char buffer[buffer_len];
00374 ERR_error_string_n(e, buffer, buffer_len);
00375 express_cat.debug() << buffer << "\n";
00376 }
00377 e = ERR_get_error();
00378 }
00379 #endif // REPORT_OPENSSL_ERRORS
00380 }
00381
00382
00383
00384
00385
00386
00387 OpenSSLWrapper *OpenSSLWrapper::
00388 get_global_ptr() {
00389 if (_global_ptr == NULL) {
00390 _global_ptr = new OpenSSLWrapper;
00391 }
00392 return _global_ptr;
00393 }
00394
00395 #endif // HAVE_OPENSSL