1 karl 1.45 //%2005////////////////////////////////////////////////////////////////////////
|
2 kumpf 1.1 //
|
3 karl 1.39 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
4 // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
5 // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
|
6 karl 1.23 // IBM Corp.; EMC Corporation, The Open Group.
|
7 karl 1.39 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
8 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
|
9 karl 1.45 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
|
11 kumpf 1.1 //
12 // Permission is hereby granted, free of charge, to any person obtaining a copy
|
13 kumpf 1.2 // of this software and associated documentation files (the "Software"), to
14 // deal in the Software without restriction, including without limitation the
15 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
16 kumpf 1.1 // sell copies of the Software, and to permit persons to whom the Software is
17 // furnished to do so, subject to the following conditions:
18 //
|
19 kumpf 1.2 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
|
20 kumpf 1.1 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
21 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
22 kumpf 1.2 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
23 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
25 kumpf 1.1 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 //==============================================================================
29 //
30 // Author: Markus Mueller (sedgewick_de@yahoo.de)
31 //
|
32 kumpf 1.9 // Modified By: Nag Boranna, Hewlett-Packard Company (nagaraja_boranna@hp.com)
33 // Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com)
|
34 h.sterling 1.26 // Sushma Fernandes, Hewlett-Packard Company (sushma_fernandes@hp.com)
35 // Heather Sterling, IBM (hsterl@us.ibm.com)
|
36 a.arora 1.35 // Amit K Arora, IBM (amita@in.ibm.com) for Bug#1090
|
37 kumpf 1.1 //
38 //%/////////////////////////////////////////////////////////////////////////////
39
40 #ifdef PEGASUS_HAS_SSL
|
41 h.sterling 1.43
42 #ifdef PEGASUS_PLATFORM_WIN32_IX86_MSVC
43 //Bugzilla 2366
44 //Use the X509_NAME in wincrypt.h on Windows. See X509.h for more info.
45 #include <windows.h>
46 #include <wincrypt.h>
47 #endif
48
|
49 mday 1.19 #define OPENSSL_NO_KRB5 1
|
50 kumpf 1.1 #include <openssl/err.h>
51 #include <openssl/ssl.h>
52 #include <openssl/rand.h>
53 #else
54 #define SSL_CTX void
55 #endif // end of PEGASUS_HAS_SSL
56 #include <Pegasus/Common/Socket.h>
57 #include <Pegasus/Common/Tracer.h>
|
58 kumpf 1.14 #include <Pegasus/Common/FileSystem.h>
|
59 kumpf 1.16 #include <time.h>
|
60 humberto 1.18 #include <Pegasus/Common/MessageLoader.h> //l10n
|
61 h.sterling 1.40 #include <Pegasus/Common/Formatter.h>
|
62 kumpf 1.1
63 #include "SSLContext.h"
64 #include "SSLContextRep.h"
65
|
66 chuck 1.53 #ifdef PEGASUS_OS_OS400
67 #include "SSLWrapperOS400.h"
68 #endif
|
69 david.dillard 1.38
70 //
71 // Typedef's for OpenSSL callback functions.
72 //
73 extern "C"
74 {
75 typedef void (* CRYPTO_SET_LOCKING_CALLBACK)(int, int, const char *, int);
76 typedef unsigned long (* CRYPTO_SET_ID_CALLBACK)(void);
77 };
78
|
79 h.sterling 1.42 typedef struct x509_store_ctx_st X509_STORE_CTX;
|
80 david.dillard 1.38
|
81 kumpf 1.16 typedef struct Timestamp
82 {
83 char year[4];
84 char month[2];
85 char day[2];
86 char hour[2];
87 char minutes[2];
88 char seconds[2];
89 char dot;
90 char microSeconds[6];
91 char plusOrMinus;
92 char utcOffset[3];
93 char padding[3];
94 } Timestamp_t;
95
|
96 kumpf 1.1 PEGASUS_USING_STD;
97
98 PEGASUS_NAMESPACE_BEGIN
99
|
100 h.sterling 1.32 const int SSLCallbackInfo::SSL_CALLBACK_INDEX = 0;
101
|
102 kumpf 1.1 //
103 // use the following definitions only if SSL is available
104 //
|
105 kumpf 1.3 #ifdef PEGASUS_HAS_SSL
|
106 kumpf 1.1
|
107 kumpf 1.15 // Mutex for SSL locks.
108 Mutex* SSLContextRep::_sslLocks = 0;
109
110 // Mutex for _countRep.
111 Mutex SSLContextRep::_countRepMutex;
112
113 // Initialise _count for SSLContextRep objects.
114 int SSLContextRep::_countRep = 0;
115
|
116 kumpf 1.16
117 //
118 // Convert ASN1_UTCTIME to CIMDateTime
119 //
120 CIMDateTime getDateTime(const ASN1_UTCTIME *utcTime)
121 {
122 struct tm time;
123 int offset;
124 Timestamp_t timeStamp;
125 char tempString[80];
126 char plusOrMinus = '+';
|
127 kumpf 1.34 unsigned char* utcTimeData = utcTime->data;
|
128 kumpf 1.16
129 memset(&time, '\0', sizeof(time));
130
131 #define g2(p) ( ( (p)[0] - '0' ) * 10 + (p)[1] - '0' )
132
|
133 kumpf 1.34 if (utcTime->type == V_ASN1_GENERALIZEDTIME)
134 {
135 time.tm_year = g2(utcTimeData) * 100;
136 utcTimeData += 2; // Remaining data is equivalent to ASN1_UTCTIME type
137 time.tm_year += g2(utcTimeData);
138 }
139 else
|
140 kumpf 1.16 {
|
141 kumpf 1.34 time.tm_year = g2(utcTimeData);
142 if (time.tm_year < 50)
143 {
144 time.tm_year += 2000;
145 }
146 else
147 {
148 time.tm_year += 1900;
149 }
|
150 kumpf 1.16 }
151
|
152 kumpf 1.34 time.tm_mon = g2(utcTimeData + 2) - 1;
153 time.tm_mday = g2(utcTimeData + 4);
154 time.tm_hour = g2(utcTimeData + 6);
155 time.tm_min = g2(utcTimeData + 8);
156 time.tm_sec = g2(utcTimeData + 10);
157
158 if (utcTimeData[12] == 'Z')
|
159 kumpf 1.16 {
160 offset = 0;
161 }
162 else
163 {
|
164 kumpf 1.34 offset = g2(utcTimeData + 13) * 60 + g2(utcTimeData + 15);
165 if (utcTimeData[12] == '-')
|
166 kumpf 1.16 {
167 plusOrMinus = '-';
168 }
169 }
170 #undef g2
171
172 memset((void *)&timeStamp, 0, sizeof(Timestamp_t));
173
174 // Format the date.
175 sprintf((char *) &timeStamp,"%04d%02d%02d%02d%02d%02d.%06d%04d",
|
176 kumpf 1.34 time.tm_year,
|
177 kumpf 1.16 time.tm_mon + 1,
178 time.tm_mday,
179 time.tm_hour,
180 time.tm_min,
181 time.tm_sec,
182 0,
183 offset);
184
185 timeStamp.plusOrMinus = plusOrMinus;
186
187 CIMDateTime dateTime;
188
189 dateTime.clear();
190 strcpy(tempString, (char *)&timeStamp);
191 dateTime.set(tempString);
192
193 return (dateTime);
194 }
195
196 //
|
197 h.sterling 1.40 // Static class used to define C++ callback functions for OpenSSL.
|
198 david.dillard 1.38 //
199 class SSLCallback
200 {
201
202 public:
|
203 h.sterling 1.47 static int verificationCallback(int preVerifyOk, X509_STORE_CTX *ctx);
204 static int verificationCRLCallback(int ok, X509_STORE_CTX *ctx, X509_STORE* sslCRLStore);
|
205 david.dillard 1.38 };
206
207 //
|
208 kumpf 1.16 // Callback function that is called by the OpenSSL library. This function
|
209 h.sterling 1.40 // checks whether the certificate is listed in any of the CRL's
210 //
|
211 h.sterling 1.47 // return 1 if revoked, 0 otherwise
212 //
|
213 h.sterling 1.40 int SSLCallback::verificationCRLCallback(int ok, X509_STORE_CTX *ctx, X509_STORE* sslCRLStore)
214 {
|
215 h.sterling 1.47 PEG_METHOD_ENTER(TRC_SSL, "SSLCallback::verificationCRLCallback");
|
216 h.sterling 1.40
|
217 h.sterling 1.47 char buf[1024];
|
218 h.sterling 1.46
|
219 h.sterling 1.47 //check whether a CRL store was specified
|
220 h.sterling 1.46 if (sslCRLStore == NULL)
221 {
222 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL3, "---> SSL: CRL store is NULL");
|
223 h.sterling 1.47 return 0;
|
224 h.sterling 1.46 }
225
|
226 h.sterling 1.47 //get the current certificate info
227 X509* currentCert;
228 X509_NAME* issuerName;
229 X509_NAME* subjectName;
230 ASN1_INTEGER* serialNumber;
|
231 h.sterling 1.46
232 currentCert = X509_STORE_CTX_get_current_cert(ctx);
|
233 h.sterling 1.47 subjectName = X509_get_subject_name(currentCert);
234 issuerName = X509_get_issuer_name(currentCert);
235 serialNumber = X509_get_serialNumber(currentCert);
|
236 h.sterling 1.46
|
237 h.sterling 1.47 //log certificate information
238 //this is information in the "public" key, so it does no harm to log it
|
239 h.sterling 1.46 X509_NAME_oneline(issuerName, buf, sizeof(buf));
|
240 h.sterling 1.47 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4, "---> SSL: Certificate Data: Issuer/Subject");
241 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4, buf);
242 X509_NAME_oneline(subjectName, buf, sizeof(buf));
243 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4, buf);
244
245 //initialize the CRL store
246 X509_STORE_CTX crlStoreCtx;
247 X509_STORE_CTX_init(&crlStoreCtx, sslCRLStore, NULL, NULL);
248
249 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4, "---> SSL: Initialized CRL store");
250
251 //attempt to get a CRL issued by the certificate's issuer
252 X509_OBJECT obj;
253 if (X509_STORE_get_by_subject(&crlStoreCtx, X509_LU_CRL, issuerName, &obj) <= 0)
254 {
255 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL3, "---> SSL: No CRL by that issuer");
256 return 0;
257 }
258 X509_STORE_CTX_cleanup(&crlStoreCtx);
|
259 h.sterling 1.46
|
260 h.sterling 1.47 //get CRL
|
261 h.sterling 1.46 X509_CRL* crl = obj.data.crl;
|
262 h.sterling 1.47 if (crl == NULL)
263 {
264 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4, "---> SSL: CRL is null");
265 return 0;
266 } else
267 {
|
268 h.sterling 1.46 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4, "---> SSL: Found CRL by that issuer");
|
269 h.sterling 1.47 }
|
270 h.sterling 1.46
|
271 h.sterling 1.47 //get revoked certificates
|
272 h.sterling 1.46 STACK_OF(X509_REVOKED)* revokedCerts = NULL;
273 revokedCerts = X509_CRL_get_REVOKED(crl);
|
274 h.sterling 1.47 int numRevoked = sk_X509_REVOKED_num(revokedCerts);
275 Tracer::trace(TRC_SSL, Tracer::LEVEL4,"---> SSL: Number of certificates revoked by the issuer %d\n", numRevoked);
|
276 h.sterling 1.46
|
277 h.sterling 1.47 //check whether the subject's certificate is revoked
278 X509_REVOKED* revokedCert = NULL;
279 for (int i = 0; i < sk_X509_REVOKED_num(revokedCerts); i++)
280 {
281 revokedCert = (X509_REVOKED *)sk_value(X509_CRL_get_REVOKED(crl), i);
|
282 h.sterling 1.46
|
283 h.sterling 1.47 //a matching serial number indicates revocation
284 if (ASN1_INTEGER_cmp(revokedCert->serialNumber, serialNumber) == 0)
285 {
286 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL2, "---> SSL: Certificate is revoked");
287 X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REVOKED);
288 return 1;
289 }
290 }
|
291 h.sterling 1.40
|
292 h.sterling 1.47 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4, "---> SSL: Certificate is not revoked at this level");
293
294 PEG_METHOD_EXIT();
295 return 0;
|
296 h.sterling 1.40 }
297
298 //
299 // Callback function that is called by the OpenSSL library. This function
|
300 kumpf 1.16 // extracts X509 certficate information and pass that on to client application
301 // callback function.
|
302 h.sterling 1.40 // We HAVE to build the certificate in all cases since it's needed to get the associated username out of the repository
303 // later in the transaction
|
304 kumpf 1.16 //
|
305 h.sterling 1.40 int SSLCallback::verificationCallback(int preVerifyOk, X509_STORE_CTX *ctx)
|
306 kumpf 1.1 {
|
307 david.dillard 1.38 PEG_METHOD_ENTER(TRC_SSL, "SSLCallback::callback()");
|
308 kumpf 1.1
309 char buf[256];
|
310 kumpf 1.16 X509 *currentCert;
|
311 h.sterling 1.28 SSL *ssl;
|
312 kumpf 1.16 int verifyError = X509_V_OK;
|
313 h.sterling 1.47 int revoked = -1;
|
314 h.sterling 1.40
|
315 h.sterling 1.47 Tracer::trace(TRC_SSL, Tracer::LEVEL4,
316 "--->SSL: Preverify Error %d", verifyError);
|
317 kumpf 1.1
|
318 h.sterling 1.28 //
319 // get the verification callback info specific to each SSL connection
320 //
321 ssl = (SSL*) X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
|
322 h.sterling 1.32 SSLCallbackInfo* exData = (SSLCallbackInfo*) SSL_get_ex_data(ssl, SSLCallbackInfo::SSL_CALLBACK_INDEX);
|
323 h.sterling 1.28
324 //
|
325 h.sterling 1.26 // If the SSLContext does not have an additional callback
|
326 h.sterling 1.40 // simply return the preverification error (or check the CRL)
|
327 h.sterling 1.26 // We do not need to go through the additional steps.
|
328 h.sterling 1.28 //
329 if (exData->verifyCertificateCallback == NULL)
|
330 h.sterling 1.26 {
|
331 h.sterling 1.47 Tracer::trace(TRC_SSL, Tracer::LEVEL4,
332 "--->SSL: No verification callback specified");
|
333 h.sterling 1.40
|
334 h.sterling 1.47 if (exData->_crlStore != NULL)
335 {
336 revoked = verificationCRLCallback(preVerifyOk,ctx,exData->_crlStore);
337 Tracer::trace(TRC_SSL, Tracer::LEVEL4, "---> SSL: CRL callback returned %d", revoked);
338
339 if (revoked) //with the SSL callbacks '0' indicates failure
340 {
341 PEG_METHOD_EXIT();
|
342 h.sterling 1.46 return 0;
|
343 h.sterling 1.47 }
344 }
|
345 h.sterling 1.26 }
346
|
347 kumpf 1.16 //
|
348 h.sterling 1.47 // Check to see if a CRL path is defined
349 //
350 if (exData->_crlStore != NULL)
351 {
|
352 h.sterling 1.40 revoked = verificationCRLCallback(preVerifyOk,ctx,exData->_crlStore);
|
353 h.sterling 1.47 Tracer::trace(TRC_SSL, Tracer::LEVEL4, "---> SSL: CRL callback returned %d", revoked);
|
354 h.sterling 1.46
|
355 h.sterling 1.47 if (revoked) //with the SSL callbacks '0' indicates failure
356 {
357 PEG_METHOD_EXIT();
|
358 h.sterling 1.46 return 0;
|
359 h.sterling 1.47 }
360 }
361
362 Tracer::trace(TRC_SSL, Tracer::LEVEL4, "---> SSL: CRL callback returned %d", revoked);
|
363 h.sterling 1.40
364 //
|
365 kumpf 1.16 // get the current certificate
366 //
367 currentCert = X509_STORE_CTX_get_current_cert(ctx);
|
368 kumpf 1.1
|
369 kumpf 1.16 //
370 // get the default verification error code
371 //
372 int errorCode = X509_STORE_CTX_get_error(ctx);
373
374 //
375 // get the depth of certificate chain
376 //
377 int depth = X509_STORE_CTX_get_error_depth(ctx);
|
378 kumpf 1.1
|
379 kumpf 1.16 //
380 // get the version on the certificate
381 //
382 long version = X509_get_version(currentCert);
|
383 kumpf 1.1
|
384 kumpf 1.16 //
385 // get the serial number of the certificate
386 //
387 long serialNumber = ASN1_INTEGER_get(X509_get_serialNumber(currentCert));
388
389 //
390 // get the validity of the certificate
391 //
392 CIMDateTime notBefore = getDateTime(X509_get_notBefore(currentCert));
393
394 CIMDateTime notAfter = getDateTime(X509_get_notAfter(currentCert));
395
396 //
397 // get the subject name on the certificate
398 //
399 X509_NAME_oneline(X509_get_subject_name(currentCert), buf, 256);
400 String subjectName = String(buf);
401
402 //
403 // get the default verification error string
404 //
405 kumpf 1.16 String errorStr = String(X509_verify_cert_error_string(errorCode));
|
406 kumpf 1.1
|
407 kumpf 1.16 //
408 // log the error string if the default verification was failed
409 //
410 if (!preVerifyOk)
|
411 kumpf 1.1 {
|
412 h.sterling 1.40 Tracer::trace(TRC_SSL, Tracer::LEVEL4,
|
413 h.sterling 1.47 "---> SSL: certificate default verification error: %s", (const char*)errorStr.getCString());
|
414 kumpf 1.1 }
415
|
416 kumpf 1.16 //
417 // get the issuer name on the certificate
418 //
419 if (!preVerifyOk && (errorCode == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT))
|
420 kumpf 1.1 {
421 X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256);
422 }
423 else
424 {
|
425 kumpf 1.16 X509_NAME_oneline(X509_get_issuer_name(currentCert), buf, 256);
|
426 kumpf 1.1 }
|
427 kumpf 1.16 String issuerName = String(buf);
|
428 kumpf 1.1
|
429 h.sterling 1.47 //
430 // Create the certificate object
431 //
|
432 h.sterling 1.54 if (exData->_peerCertificate != NULL)
433 {
434 //Delete an existing certificate object from a previous call.
435 //SSL validates the certificate chain starting with the root CA and working down to the peer certificate.
436 //With this strategy, we end up with the peer certificate as the last certificate stored in the SSLCallbackInfo
437 //so we can retrieve the correct certificate info and username.
438 delete exData->_peerCertificate;
439 exData->_peerCertificate = NULL;
440 }
441
|
442 h.sterling 1.28 exData->_peerCertificate = new SSLCertificateInfo(subjectName, issuerName, version, serialNumber,
443 notBefore, notAfter, depth, errorCode, errorStr, preVerifyOk);
444
|
445 kumpf 1.1 //
|
446 h.sterling 1.28 // Call the application callback.
447 // Note that the verification result does not automatically get set to X509_V_OK if the callback is successful.
448 // This is because OpenSSL retains the original default error in case we want to use it later.
449 // To set the error, we could use X509_STORE_CTX_set_error(ctx, verifyError); but there is no real benefit to doing that here.
|
450 kumpf 1.1 //
|
451 h.sterling 1.40 if (exData->verifyCertificateCallback(*exData->_peerCertificate))
|
452 kumpf 1.1 {
|
453 kumpf 1.16 Tracer::trace(TRC_SSL, Tracer::LEVEL4,
|
454 h.sterling 1.28 "--> SSL: verifyCertificateCallback() returned X509_V_OK");
455
456 PEG_METHOD_EXIT();
457 return 1;
|
458 kumpf 1.16 }
|
459 h.sterling 1.28 else // verification failed, handshake will be immediately terminated
|
460 kumpf 1.16 {
461 Tracer::trace(TRC_SSL, Tracer::LEVEL4,
|
462 h.sterling 1.28 "--> SSL: verifyCertificateCallback() returned error %d", exData->_peerCertificate->getErrorCode());
463
464 PEG_METHOD_EXIT();
465 return 0;
|
466 kumpf 1.1 }
467 }
468
|
469 kumpf 1.15 //
|
470 david.dillard 1.38 // Callback function called by OpenSSL. This request is merely forwarded to the static
471 // function SSLCallback::callback(). The SSLCallback class is a friend class of the
472 // Pegasus SSL related classes needed to complete the callback.
473 //
474 extern "C" int prepareForCallback(int preVerifyOk, X509_STORE_CTX *ctx)
475 {
|
476 h.sterling 1.40 return SSLCallback::verificationCallback(preVerifyOk, ctx);
|
477 david.dillard 1.38 }
478
479 //
|
480 kumpf 1.15 // Implement OpenSSL locking callback.
481 //
|
482 h.sterling 1.47 void pegasus_locking_callback( int mode,
483 int type,
484 const char* file,
485 int line)
|
486 kumpf 1.15 {
487 // Check whether the mode is lock or unlock.
488
489 if ( mode & CRYPTO_LOCK )
490 {
|
491 h.sterling 1.26 /*Tracer::trace(TRC_SSL, Tracer::LEVEL4,
492 "Now locking for %d", pegasus_thread_self());*/
|
493 kumpf 1.15 SSLContextRep::_sslLocks[type].lock( pegasus_thread_self() );
494 }
495 else
496 {
|
497 h.sterling 1.26 /*Tracer::trace(TRC_SSL, Tracer::LEVEL4,
498 "Now unlocking for %d", pegasus_thread_self());*/
|
499 kumpf 1.15 SSLContextRep::_sslLocks[type].unlock( );
500 }
501 }
502
503 //
504 // Initialize OpenSSL Locking and id callbacks.
505 //
506 void SSLContextRep::init_ssl()
507 {
508 // Allocate Memory for _sslLocks. SSL locks needs to be able to handle
509 // up to CRYPTO_num_locks() different mutex locks.
510 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,
511 "Initialized SSL callback.");
512
|
513 chuck 1.53 #ifdef PEGASUS_OS_OS400
514 // Load the OpenSSL library and get the exports
515 SSL_OS400_Init();
516 #endif
517
|
518 kumpf 1.15 _sslLocks= new Mutex[CRYPTO_num_locks()];
519
520 // Set the ID callback. The ID callback returns a thread ID.
521
|
522 david.dillard 1.38 CRYPTO_set_id_callback((CRYPTO_SET_ID_CALLBACK) pegasus_thread_self);
|
523 kumpf 1.15
524 // Set the locking callback to pegasus_locking_callback.
525
|
526 david.dillard 1.38 CRYPTO_set_locking_callback((CRYPTO_SET_LOCKING_CALLBACK) pegasus_locking_callback);
|
527 kumpf 1.15
528 }
529
530 // Free OpenSSL Locking and id callbacks.
531 void SSLContextRep::free_ssl()
532 {
533 // Cleanup _sslLocks and set locking & id callback to NULL.
534
535 CRYPTO_set_locking_callback(NULL);
536 CRYPTO_set_id_callback (NULL);
537 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,
538 "Freed SSL callback.");
539
540 delete []_sslLocks;
541 }
542
|
543 kumpf 1.1
544 //
545 // SSL context area
546 //
547 // For the OSs that don't have /dev/random device file,
548 // must enable PEGASUS_SSL_RANDOMFILE flag.
549 //
|
550 h.sterling 1.26 SSLContextRep::SSLContextRep(
551 const String& trustStore,
552 const String& certPath,
553 const String& keyPath,
|
554 h.sterling 1.47 const String& crlPath,
|
555 h.sterling 1.26 SSLCertificateVerifyFunction* verifyCert,
556 const String& randomFile)
557 {
558 PEG_METHOD_ENTER(TRC_SSL, "SSLContextRep::SSLContextRep()");
559
560 _trustStore = trustStore;
561
562 _certPath = certPath;
563
564 _keyPath = keyPath;
565
|
566 h.sterling 1.40 _crlPath = crlPath;
|
567 h.sterling 1.26
|
568 h.sterling 1.47 _crlStore = NULL;
|
569 h.sterling 1.26
|
570 h.sterling 1.40 _certificateVerifyFunction = verifyCert;
|
571 h.sterling 1.26
|
572 h.sterling 1.28 //
|
573 h.sterling 1.26 // If a truststore and/or peer verification function is specified, enable peer verification
|
574 h.sterling 1.28 //
|
575 h.sterling 1.26 if (trustStore != String::EMPTY || verifyCert != NULL)
576 {
577 _verifyPeer = true;
578 }
579 else
580 {
581 _verifyPeer = false;
582 }
|
583 kumpf 1.15
|
584 h.sterling 1.28 //
|
585 kumpf 1.15 // Initialiaze SSL callbacks and increment the SSLContextRep object _counter.
|
586 h.sterling 1.28 //
|
587 a.arora 1.35 {
588 AutoMutex autoMut(_countRepMutex);
|
589 kumpf 1.15
|
590 a.arora 1.35 Tracer::trace(TRC_SSL, Tracer::LEVEL4,
|
591 kumpf 1.15 "Value of Countrep in constructor %d", _countRep);
592 if ( _countRep == 0 )
593 {
594 init_ssl();
595
596 //
597 // load SSL library
598 //
599 Tracer::trace(TRC_SSL, Tracer::LEVEL4,
600 "Before calling SSL_load_error_strings %d", pegasus_thread_self());
601
602 SSL_load_error_strings();
603
604 Tracer::trace(TRC_SSL, Tracer::LEVEL4,
605 "After calling SSL_load_error_strings %d", pegasus_thread_self());
606
607 Tracer::trace(TRC_SSL, Tracer::LEVEL4,
608 "Before calling SSL_library_init %d", pegasus_thread_self());
609
610 SSL_library_init();
611
612 kumpf 1.15 Tracer::trace(TRC_SSL, Tracer::LEVEL4,
613 "After calling SSL_library_init %d", pegasus_thread_self());
614
615 }
|
616 h.sterling 1.40
|
617 kumpf 1.15 _countRep++;
|
618 a.arora 1.35 } // mutex unlocks here
|
619 kumpf 1.1
|
620 kumpf 1.14 _randomInit(randomFile);
|
621 kumpf 1.1
|
622 kumpf 1.9 _sslContext = _makeSSLContext();
623
624 PEG_METHOD_EXIT();
625 }
626
627 SSLContextRep::SSLContextRep(const SSLContextRep& sslContextRep)
628 {
629 PEG_METHOD_ENTER(TRC_SSL, "SSLContextRep::SSLContextRep()");
630
|
631 h.sterling 1.26 _trustStore = sslContextRep._trustStore;
|
632 kumpf 1.9 _certPath = sslContextRep._certPath;
|
633 kumpf 1.16 _keyPath = sslContextRep._keyPath;
|
634 h.sterling 1.47 _crlPath = sslContextRep._crlPath;
|
635 h.sterling 1.50 _crlStore = sslContextRep._crlStore;
|
636 h.sterling 1.26 _verifyPeer = sslContextRep._verifyPeer;
|
637 h.sterling 1.28 _certificateVerifyFunction = sslContextRep._certificateVerifyFunction;
|
638 kumpf 1.9 _randomFile = sslContextRep._randomFile;
|
639 kumpf 1.15
640 // Initialiaze SSL callbacks and increment the SSLContextRep object _counter.
641 {
|
642 a.arora 1.35 AutoMutex autoMut(_countRepMutex);
|
643 kumpf 1.15 Tracer::trace(TRC_SSL, Tracer::LEVEL4,
644 "Value of Countrep in copy constructor %d", _countRep);
645 if ( _countRep == 0 )
646 {
647 init_ssl();
648 }
|
649 h.sterling 1.40
|
650 kumpf 1.15 _countRep++;
|
651 a.arora 1.35 } // mutex unlocks here
|
652 kumpf 1.15
|
653 kumpf 1.9 _sslContext = _makeSSLContext();
654 PEG_METHOD_EXIT();
655 }
|
656 kumpf 1.11
|
657 kumpf 1.9 //
658 // Destructor
659 //
660
661 SSLContextRep::~SSLContextRep()
662 {
663 PEG_METHOD_ENTER(TRC_SSL, "SSLContextRep::~SSLContextRep()");
664
665 SSL_CTX_free(_sslContext);
666
|
667 kumpf 1.15 // Decrement the SSLContextRep object _counter.
668 {
|
669 a.arora 1.35 AutoMutex autoMut(_countRepMutex);
670 _countRep--;
671 // Free SSL locks if no instances of SSLContextRep exist.
672
|
673 kumpf 1.15 Tracer::trace(TRC_SSL, Tracer::LEVEL4,
674 "Value of Countrep in destructor %d", _countRep);
675 if ( _countRep == 0 )
676 {
677 free_ssl();
678 }
|
679 alagaraja 1.36
|
680 kumpf 1.15 }
|
681 kumpf 1.9 PEG_METHOD_EXIT();
682 }
683
|
684 kumpf 1.14 //
685 // initialize OpenSSL's PRNG
686 //
687 void SSLContextRep::_randomInit(const String& randomFile)
688 {
689 PEG_METHOD_ENTER(TRC_SSL, "SSLContextRep::_randomInit()");
690
691 Boolean ret;
692 int retVal = 0;
693
694 #ifdef PEGASUS_SSL_RANDOMFILE
695 if ( RAND_status() == 0 )
696 {
697 //
698 // Initialise OpenSSL random number generator.
699 //
700 if ( randomFile == String::EMPTY )
701 {
702 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,
703 "Random seed file is required.");
704 PEG_METHOD_EXIT();
|
705 humberto 1.18 //l10n
706 //throw( SSLException("Random seed file required"));
707 MessageLoaderParms parms("Common.SSLContext.RANDOM_SEED_FILE_REQUIRED",
|
708 h.sterling 1.47 "Random seed file required");
709 throw SSLException(parms);
|
710 kumpf 1.14 }
711
712 //
713 // Try the given random seed file
714 //
715 ret = FileSystem::exists(randomFile);
716 if( ret )
717 {
|
718 kumpf 1.15 retVal = RAND_load_file(randomFile.getCString(), -1);
|
719 kumpf 1.14 if ( retVal < 0 )
720 {
721 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,
722 "Not enough seed data in seed file: " + randomFile);
723 PEG_METHOD_EXIT();
|
724 humberto 1.18 //l10n
|
725 h.sterling 1.47 // do not put in $0 in default message, but pass in filename for bundle message
|
726 humberto 1.18 //throw( SSLException("Not enough seed data in random seed file."));
727 MessageLoaderParms parms("Common.SSLContext.NOT_ENOUGH_SEED_DATA_IN_FILE",
|
728 h.sterling 1.47 "Not enough seed data in random seed file.",
729 randomFile);
730 throw SSLException(parms);
|
731 kumpf 1.14 }
732 }
|
733 kumpf 1.16 else
734 {
735 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,
736 "seed file - " + randomFile + " does not exist.");
737 PEG_METHOD_EXIT();
|
738 humberto 1.18 //l10n
739 //throw( SSLException("Seed file '" + randomFile + "' does not exist."));
740 MessageLoaderParms parms("Common.SSLContext.SEED_FILE_DOES_NOT_EXIST",
|
741 h.sterling 1.47 "Seed file '$0' does not exist.",
742 randomFile);
|
743 tony 1.24 throw SSLException(parms);
|
744 kumpf 1.16 }
|
745 kumpf 1.14
746 if ( RAND_status() == 0 )
747 {
748 //
749 // Try to do more seeding
750 //
751 long seedNumber;
|
752 tony 1.24 #if defined(PEGASUS_PLATFORM_WIN32_IX86_MSVC)
753 srand((unsigned int)time(NULL)); // Initialize
754 seedNumber = rand();
755 #else
|
756 kumpf 1.14 srandom((unsigned int)time(NULL)); // Initialize
757 seedNumber = random();
|
758 tony 1.24 #endif
|
759 kumpf 1.14 RAND_seed((unsigned char *) &seedNumber, sizeof(seedNumber));
760
761 int seedRet = RAND_status();
762 if ( seedRet == 0 )
763 {
764 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,
|
765 kumpf 1.15 "Not enough seed data in random seed file, RAND_status = " +
766 seedRet);
|
767 kumpf 1.14 PEG_METHOD_EXIT();
|
768 humberto 1.22 //l10n 485
|
769 h.sterling 1.47 // do not put in $0 in default message, but pass in filename for bundle message
|
770 humberto 1.18 //throw( SSLException("Not enough seed data in random seed file."));
771 MessageLoaderParms parms("Common.SSLContext.NOT_ENOUGH_SEED_DATA_IN_FILE",
|
772 h.sterling 1.47 "Not enough seed data in random seed file.",
773 randomFile);
774 throw SSLException(parms);
|
775 kumpf 1.14 }
776 }
777 }
778 #endif /* PEGASUS_SSL_RANDOMFILE */
779
780 int seedRet = RAND_status();
781 if ( seedRet == 0 )
782 {
783 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,
784 "Not enough seed data , RAND_status = " + seedRet );
785 PEG_METHOD_EXIT();
|
786 humberto 1.18 //l10n
787 //throw( SSLException("Not enough seed data."));
788 MessageLoaderParms parms("Common.SSLContext.NOT_ENOUGH_SEED_DATA",
|
789 h.sterling 1.47 "Not enough seed data.");
|
790 tony 1.24 throw SSLException(parms);
|
791 kumpf 1.14 }
792
793 PEG_METHOD_EXIT();
794 }
795
|
796 kumpf 1.9 SSL_CTX * SSLContextRep::_makeSSLContext()
797 {
798 PEG_METHOD_ENTER(TRC_SSL, "SSLContextRep::_makeSSLContext()");
799
800 SSL_CTX * sslContext = 0;
801
|
802 kumpf 1.1 //
803 // create SSL Context Area
804 //
805
|
806 kumpf 1.9 if (!( sslContext = SSL_CTX_new(SSLv23_method()) ))
|
807 kumpf 1.3 {
808 PEG_METHOD_EXIT();
|
809 humberto 1.18 //l10n
810 //throw( SSLException("Could not get SSL CTX"));
811 MessageLoaderParms parms("Common.SSLContext.COULD_NOT_GET",
|
812 h.sterling 1.47 "Could not get SSL CTX");
|
813 tony 1.24 throw SSLException(parms);
|
814 kumpf 1.3 }
815
|
816 kumpf 1.14 #ifdef PEGASUS_SSL_WEAKENCRYPTION
|
817 humberto 1.18 if (!(SSL_CTX_set_cipher_list(sslContext, SSL_TXT_EXP40))){
|
818 h.sterling 1.47 //l10n
|
819 humberto 1.18 //throw( SSLException("Could not set the cipher list"));
820 MessageLoaderParms parms("Common.SSLContext.COULD_NOT_SET_CIPHER_LIST",
|
821 h.sterling 1.47 "Could not set the cipher list");
|
822 tony 1.24 throw SSLException(parms);
|
823 humberto 1.18 }
|
824 kumpf 1.3 #endif
|
825 kumpf 1.1
826 //
827 // set overall SSL Context flags
828 //
829
|
830 kumpf 1.9 SSL_CTX_set_quiet_shutdown(sslContext, 1);
831 SSL_CTX_set_mode(sslContext, SSL_MODE_AUTO_RETRY);
|
832 kumpf 1.14 SSL_CTX_set_session_cache_mode(sslContext, SSL_SESS_CACHE_OFF);
|
833 kumpf 1.1
|
834 h.sterling 1.50 int options = SSL_OP_ALL;
|
835 h.sterling 1.49 #ifndef PEGASUS_ENABLE_SSLV2 //SSLv2 is disabled by default
|
836 h.sterling 1.50 options |= SSL_OP_NO_SSLv2;
|
837 h.sterling 1.49 #endif
|
838 h.sterling 1.50 SSL_CTX_set_options(sslContext, options);
|
839 h.sterling 1.49
|
840 h.sterling 1.26 if (_verifyPeer)
|
841 kumpf 1.1 {
|
842 h.sterling 1.26 //ATTN: We might still need a flag to specify SSL_VERIFY_FAIL_IF_NO_PEER_CERT
|
843 kumpf 1.27 // If SSL_VERIFY_FAIL_IF_NO_PEER_CERT is ON, SSL will immediately be terminated
844 // if the client sends no certificate or sends an untrusted certificate. The
845 // callback function is not called in this case; the handshake is simply terminated.
|
846 h.sterling 1.26 // This value has NO effect in from a client perspective
847
|
848 h.sterling 1.28 if (_certificateVerifyFunction != NULL)
|
849 h.sterling 1.26 {
|
850 kumpf 1.27 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL3,
851 "---> SSL: certificate verification callback specified");
852 SSL_CTX_set_verify(sslContext,
853 SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, prepareForCallback);
854 }
|
855 h.sterling 1.26 else
856 {
|
857 kumpf 1.27 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL3, "---> SSL: Trust Store specified");
858 SSL_CTX_set_verify(sslContext,
859 SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
860 prepareForCallback);
|
861 h.sterling 1.26 }
|
862 kumpf 1.1 }
|
863 kumpf 1.14 else
864 {
|
865 kumpf 1.27 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL3,
866 "---> SSL: Trust Store and certificate verification callback are NOT specified");
867 SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL);
|
868 kumpf 1.14 }
|
869 kumpf 1.1
870 //
|
871 kumpf 1.27 // Check if there is CA certificate file or directory specified. If specified,
872 // and is not empty, load the certificates from the Trust store.
|
873 h.sterling 1.26 //
|
874 kumpf 1.27 if (_trustStore != String::EMPTY)
|
875 kumpf 1.14 {
876 //
|
877 h.sterling 1.26 // The truststore may be a single file of CA certificates OR
878 // a directory containing multiple CA certificates.
879 // Check which one it is, and call the load_verify_locations function
880 // with the appropriate parameter. Note: It is possible to have both
|
881 kumpf 1.27 // options, in which case the CA file takes precedence over the CA path.
|
882 h.sterling 1.26 // However, since there is currently only one trust parameter to the
883 // SSL functions, only allow one choice here.
|
884 kumpf 1.27 //
885 if (FileSystem::isDirectory(_trustStore))
886 {
887 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL3,
888 "---> SSL: Truststore is a directory");
889 //
890 // load certificates from the trust store
891 //
892 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL2,
893 "---> SSL: Loading certificates from the trust store: " + _trustStore);
894
895 if ((!SSL_CTX_load_verify_locations(sslContext, NULL, _trustStore.getCString())) ||
896 (!SSL_CTX_set_default_verify_paths(sslContext)))
897 {
898 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL2,
899 "---> SSL: Could not load certificates from the trust store: " + _trustStore);
900 //l10n
901 MessageLoaderParms parms("Common.SSLContext.COULD_NOT_LOAD_CERTIFICATES",
902 "Could not load certificates in to trust store.");
903 PEG_METHOD_EXIT();
904 throw SSLException(parms);
905 kumpf 1.27 }
|
906 h.sterling 1.26
|
907 kumpf 1.27 }
908 else if (FileSystem::exists(_trustStore))
|
909 h.sterling 1.26 {
|
910 kumpf 1.27 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL3,
911 "---> SSL: Truststore is a file");
912 //
913 // Get size of the trust store file:
914 //
915 Uint32 fileSize = 0;
|
916 h.sterling 1.26
|
917 kumpf 1.27 FileSystem::getFileSize(_trustStore, fileSize);
|
918 h.sterling 1.26
|
919 kumpf 1.27 if (fileSize > 0)
920 {
921 //
922 // load certificates from the trust store
923 //
924 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL2,
925 "---> SSL: Loading certificates from the trust store: " + _trustStore);
926
927 if ((!SSL_CTX_load_verify_locations(sslContext, _trustStore.getCString(), NULL)) ||
928 (!SSL_CTX_set_default_verify_paths(sslContext)))
929 {
930 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL2,
931 "---> SSL: Could not load certificates from the trust store: " + _trustStore);
932 //l10n
933 MessageLoaderParms parms("Common.SSLContext.COULD_NOT_LOAD_CERTIFICATES",
934 "Could not load certificates in to trust store.");
935 PEG_METHOD_EXIT();
936 throw SSLException(parms);
937 }
938 }
939 else
940 kumpf 1.27 {
941 //
942 // no certificates found in the trust store
943 //
944 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL2,
945 "---> SSL: No certificates to load from the trust store: " + _trustStore);
946 }
|
947 kumpf 1.14 }
948 }
949
|
950 h.sterling 1.47 if (_crlPath != String::EMPTY)
951 {
|
952 h.sterling 1.40 //need to save this -- can we make it static since there's only one CRL for cimserver?
|
953 h.sterling 1.47 X509_LOOKUP* pLookup;
954
955 _crlStore = X509_STORE_new();
|
956 h.sterling 1.40
|
957 h.sterling 1.47 //the validity of the crlstore was checked in ConfigManager during server startup
958 if (FileSystem::isDirectory(_crlPath))
|
959 h.sterling 1.40 {
960 Tracer::trace(TRC_SSL, Tracer::LEVEL3,
|
961 h.sterling 1.47 "---> SSL: CRL store is a directory in %s", (const char*)_crlPath.getCString());
|
962 h.sterling 1.40
963 if ((pLookup = X509_STORE_add_lookup(_crlStore, X509_LOOKUP_hash_dir())) == NULL)
|
964 h.sterling 1.47 {
965 MessageLoaderParms parms("Common.SSLContext.COULD_NOT_LOAD_CRLS",
966 "Could not load certificate revocation list.");
967 X509_STORE_free(_crlStore);
|
968 h.sterling 1.40 PEG_METHOD_EXIT();
969 throw SSLException(parms);
|
970 h.sterling 1.47 }
|
971 h.sterling 1.40
972 X509_LOOKUP_add_dir(pLookup, (const char*)_crlPath.getCString(), X509_FILETYPE_PEM);
973
974 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL3,
975 "---> SSL: Successfully configured CRL directory");
976
|
977 h.sterling 1.47 } else
978 {
|
979 h.sterling 1.40 Tracer::trace(TRC_SSL, Tracer::LEVEL3,
|
980 h.sterling 1.47 "---> SSL: CRL store is the file %s", (const char*)_crlPath.getCString());
|
981 h.sterling 1.40
982 if ((pLookup = X509_STORE_add_lookup(_crlStore, X509_LOOKUP_file())) == NULL)
|
983 h.sterling 1.47 {
|
984 h.sterling 1.40 MessageLoaderParms parms("Common.SSLContext.COULD_NOT_LOAD_CRLS",
|
985 h.sterling 1.47 "Could not load certificate revocation list.");
986 X509_STORE_free(_crlStore);
|
987 h.sterling 1.40 PEG_METHOD_EXIT();
988 throw SSLException(parms);
|
989 h.sterling 1.47 }
|
990 h.sterling 1.40
|
991 h.sterling 1.47 X509_LOOKUP_load_file(pLookup, (const char*)_crlPath.getCString(), X509_FILETYPE_PEM);
992
993 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL3,
994 "---> SSL: Successfully configured CRL file");
995 }
996 }
|
997 h.sterling 1.40
|
998 kumpf 1.17 Boolean keyLoaded = false;
|
999 kumpf 1.27
|
1000 kumpf 1.1 //
|
1001 kumpf 1.16 // Check if there is a certificate file (file containing server
1002 // certificate) specified. If specified, validate and load the
1003 // certificate.
|
1004 kumpf 1.14 //
|
1005 kumpf 1.27 if (_certPath != String::EMPTY)
|
1006 kumpf 1.14 {
1007 //
1008 // load the specified server certificates
1009 //
|
1010 kumpf 1.27 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL2,
1011 "---> SSL: Loading server certificate from: " + _certPath);
|
1012 kumpf 1.1
|
1013 kumpf 1.27 if (SSL_CTX_use_certificate_file(sslContext,
1014 _certPath.getCString(), SSL_FILETYPE_PEM) <=0)
|
1015 kumpf 1.14 {
|
1016 kumpf 1.27 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL2,
1017 "---> SSL: No server certificate found in " + _certPath);
|
1018 humberto 1.18 MessageLoaderParms parms("Common.SSLContext.COULD_NOT_GET_SERVER_CERTIFICATE",
|
1019 h.sterling 1.47 "Could not get server certificate.");
|
1020 kumpf 1.27 PEG_METHOD_EXIT();
|
1021 tony 1.24 throw SSLException(parms);
|
1022 kumpf 1.14 }
|
1023 kumpf 1.17
|
1024 kumpf 1.16 //
1025 // If there is no key file (file containing server
|
1026 h.sterling 1.26 // private key) specified, then try loading the key from the certificate file.
|
1027 kumpf 1.27 // As of 2.4, if a keyfile is specified, its location is verified during server
1028 // startup and will throw an error if the path is invalid.
|
1029 kumpf 1.16 //
|
1030 kumpf 1.27 if (_keyPath == String::EMPTY)
|
1031 kumpf 1.16 {
|
1032 kumpf 1.27 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL2,
1033 "---> SSL: loading private key from: " + _certPath);
|
1034 kumpf 1.16 //
1035 // load the private key and check for validity
1036 //
|
1037 kumpf 1.27 if (!_verifyPrivateKey(sslContext, _certPath))
|
1038 kumpf 1.16 {
|
1039 humberto 1.18 MessageLoaderParms parms("Common.SSLContext.COULD_NOT_GET_PRIVATE_KEY",
|
1040 h.sterling 1.47 "Could not get private key.");
|
1041 kumpf 1.27 PEG_METHOD_EXIT();
|
1042 h.sterling 1.47 throw SSLException(parms);
|
1043 kumpf 1.16 }
|
1044 kumpf 1.17 keyLoaded = true;
|
1045 kumpf 1.16 }
1046 }
|
1047 kumpf 1.14
|
1048 kumpf 1.16 //
|
1049 kumpf 1.17 // Check if there is a key file (file containing server
1050 // private key) specified and the key was not already loaded.
1051 // If specified, validate and load the key.
|
1052 kumpf 1.16 //
|
1053 kumpf 1.27 if (_keyPath != String::EMPTY && !keyLoaded)
|
1054 kumpf 1.16 {
|
1055 kumpf 1.27 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL2,
1056 "---> SSL: loading private key from: " + _keyPath);
|
1057 kumpf 1.14 //
1058 // load given private key and check for validity
1059 //
|
1060 kumpf 1.27 if (!_verifyPrivateKey(sslContext, _keyPath))
|
1061 kumpf 1.14 {
|
1062 humberto 1.18 MessageLoaderParms parms("Common.SSLContext.COULD_NOT_GET_PRIVATE_KEY",
|
1063 h.sterling 1.47 "Could not get private key.");
|
1064 kumpf 1.27 PEG_METHOD_EXIT();
|
1065 tony 1.24 throw SSLException(parms);
|
1066 kumpf 1.14 }
|
1067 kumpf 1.17 keyLoaded = true;
|
1068 kumpf 1.14 }
1069
1070 PEG_METHOD_EXIT();
1071 return sslContext;
1072 }
1073
|
1074 kumpf 1.27 Boolean SSLContextRep::_verifyPrivateKey(SSL_CTX *ctx, const String& keyPath)
|
1075 kumpf 1.14 {
1076 PEG_METHOD_ENTER(TRC_SSL, "_verifyPrivateKey()");
1077
|
1078 kumpf 1.27 if (SSL_CTX_use_PrivateKey_file(ctx, keyPath.getCString(), SSL_FILETYPE_PEM) <= 0)
|
1079 kumpf 1.3 {
|
1080 kumpf 1.27 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL2,
|
1081 kumpf 1.16 "---> SSL: no private key found in " + String(keyPath));
|
1082 kumpf 1.3 PEG_METHOD_EXIT();
|
1083 kumpf 1.14 return false;
1084 }
1085
1086 if (!SSL_CTX_check_private_key(ctx))
1087 {
|
1088 kumpf 1.27 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL2,
|
1089 kumpf 1.14 "---> SSL: Private and public key do not match");
1090 PEG_METHOD_EXIT();
1091 return false;
|
1092 kumpf 1.3 }
|
1093 kumpf 1.1
|
1094 kumpf 1.3 PEG_METHOD_EXIT();
|
1095 kumpf 1.14 return true;
|
1096 kumpf 1.1 }
1097
1098 SSL_CTX * SSLContextRep::getContext() const
1099 {
|
1100 kumpf 1.9 return _sslContext;
|
1101 kumpf 1.1 }
|
1102 h.sterling 1.26
1103 String SSLContextRep::getTrustStore() const
1104 {
1105 return _trustStore;
1106 }
1107
1108 String SSLContextRep::getCertPath() const
1109 {
1110 return _certPath;
1111 }
1112
1113 String SSLContextRep::getKeyPath() const
1114 {
1115 return _keyPath;
1116 }
1117
|
1118 h.sterling 1.40 String SSLContextRep::getCRLPath() const
|
1119 h.sterling 1.26 {
|
1120 h.sterling 1.40 return _crlPath;
|
1121 h.sterling 1.26 }
1122
|
1123 h.sterling 1.40 X509_STORE* SSLContextRep::getCRLStore() const
|
1124 h.sterling 1.26 {
|
1125 h.sterling 1.40 return _crlStore;
|
1126 h.sterling 1.26 }
1127
|
1128 h.sterling 1.50 void SSLContextRep::setCRLStore(X509_STORE* store)
1129 {
1130 _crlStore = store;
1131 }
1132
|
1133 h.sterling 1.40 Boolean SSLContextRep::isPeerVerificationEnabled() const
|
1134 h.sterling 1.26 {
|
1135 h.sterling 1.40 return _verifyPeer;
|
1136 h.sterling 1.26 }
1137
|
1138 h.sterling 1.28 SSLCertificateVerifyFunction* SSLContextRep::getSSLCertificateVerifyFunction() const
1139 {
1140 return _certificateVerifyFunction;
1141 }
1142
|
1143 kumpf 1.1 #else
1144
1145 //
|
1146 kumpf 1.9 // these definitions are used if ssl is not available
|
1147 kumpf 1.1 //
1148
|
1149 h.sterling 1.26 SSLContextRep::SSLContextRep(const String& trustStore,
|
1150 kumpf 1.16 const String& certPath,
1151 const String& keyPath,
|
1152 h.sterling 1.41 const String& crlPath,
|
1153 kumpf 1.9 SSLCertificateVerifyFunction* verifyCert,
|
1154 h.sterling 1.41 const String& randomFile)
1155 {}
|
1156 h.sterling 1.26
|
1157 kumpf 1.9 SSLContextRep::SSLContextRep(const SSLContextRep& sslContextRep) {}
1158
|
1159 kumpf 1.1 SSLContextRep::~SSLContextRep() {}
1160
|
1161 kumpf 1.9 SSL_CTX * SSLContextRep::_makeSSLContext() { return 0; }
1162
|
1163 kumpf 1.27 Boolean SSLContextRep::_verifyPrivateKey(SSL_CTX *ctx,
1164 const String& keyPath) { return false; }
|
1165 kumpf 1.14
|
1166 kumpf 1.9 SSL_CTX * SSLContextRep::getContext() const { return 0; }
|
1167 kumpf 1.15
|
1168 h.sterling 1.26 String SSLContextRep::getTrustStore() const { return String::EMPTY; }
1169
1170 String SSLContextRep::getCertPath() const { return String::EMPTY; }
1171
1172 String SSLContextRep::getKeyPath() const { return String::EMPTY; }
1173
|
1174 h.sterling 1.40 String SSLContextRep::getCRLPath() const { return String::EMPTY; }
|
1175 h.sterling 1.26
|
1176 h.sterling 1.40 X509_STORE* SSLContextRep::getCRLStore() const { return NULL; }
|
1177 h.sterling 1.26
|
1178 h.sterling 1.50 void SSLContextRep::setCRLStore(X509_STORE* store) { }
1179
|
1180 h.sterling 1.40 Boolean SSLContextRep::isPeerVerificationEnabled() const { return false; }
|
1181 h.sterling 1.26
|
1182 h.sterling 1.28 SSLCertificateVerifyFunction* SSLContextRep::getSSLCertificateVerifyFunction() const { return NULL; }
1183
|
1184 kumpf 1.15 void SSLContextRep::init_ssl() {}
1185
1186 void SSLContextRep::free_ssl() {}
|
1187 kumpf 1.1
1188 #endif // end of PEGASUS_HAS_SSL
1189
1190 ///////////////////////////////////////////////////////////////////////////////
1191 //
1192 // SSLContext
1193 //
1194 ///////////////////////////////////////////////////////////////////////////////
1195
1196
1197 SSLContext::SSLContext(
|
1198 h.sterling 1.26 const String& trustStore,
|
1199 kumpf 1.9 SSLCertificateVerifyFunction* verifyCert,
|
1200 kumpf 1.13 const String& randomFile)
1201 {
|
1202 h.sterling 1.40 _rep = new SSLContextRep(trustStore, String::EMPTY, String::EMPTY, String::EMPTY, verifyCert, randomFile);
|
1203 kumpf 1.13 }
1204
|
1205 kumpf 1.14 SSLContext::SSLContext(
|
1206 h.sterling 1.26 const String& trustStore,
|
1207 kumpf 1.14 const String& certPath,
|
1208 kumpf 1.16 const String& keyPath,
|
1209 kumpf 1.14 SSLCertificateVerifyFunction* verifyCert,
1210 const String& randomFile)
1211 {
|
1212 h.sterling 1.40 _rep = new SSLContextRep(trustStore, certPath, keyPath, String::EMPTY, verifyCert, randomFile);
|
1213 h.sterling 1.30 }
1214
|
1215 h.sterling 1.40 //PEP187
|
1216 h.sterling 1.26 SSLContext::SSLContext(
1217 const String& trustStore,
1218 const String& certPath,
1219 const String& keyPath,
|
1220 h.sterling 1.47 const String& crlPath,
|
1221 h.sterling 1.26 SSLCertificateVerifyFunction* verifyCert,
1222 const String& randomFile)
1223 {
|
1224 h.sterling 1.40 _rep = new SSLContextRep(trustStore, certPath, keyPath, crlPath, verifyCert, randomFile);
|
1225 kumpf 1.14 }
1226
|
1227 kumpf 1.9 SSLContext::SSLContext(const SSLContext& sslContext)
1228 {
1229 _rep = new SSLContextRep(*sslContext._rep);
|
1230 kumpf 1.12 }
1231
1232 // Dummy constructor made private to disallow default construction
1233 SSLContext::SSLContext()
1234 {
|
1235 kumpf 1.9 }
1236
|
1237 kumpf 1.1 SSLContext::~SSLContext()
1238 {
1239 delete _rep;
1240 }
1241
|
1242 h.sterling 1.26 String SSLContext::getTrustStore() const
1243 {
1244 return (_rep->getTrustStore());
1245 }
1246
1247 String SSLContext::getCertPath() const
1248 {
1249 return (_rep->getCertPath());
1250 }
1251
1252 String SSLContext::getKeyPath() const
1253 {
1254 return (_rep->getKeyPath());
1255 }
1256
|
1257 h.sterling 1.40 String SSLContext::getCRLPath() const
|
1258 h.sterling 1.26 {
|
1259 h.sterling 1.40 return (_rep->getCRLPath());
|
1260 h.sterling 1.26 }
1261
|
1262 h.sterling 1.40 X509_STORE* SSLContext::getCRLStore() const
|
1263 h.sterling 1.26 {
|
1264 h.sterling 1.40 return (_rep->getCRLStore());
|
1265 h.sterling 1.26 }
1266
|
1267 h.sterling 1.40 Boolean SSLContext::isPeerVerificationEnabled() const
|
1268 h.sterling 1.26 {
|
1269 h.sterling 1.40 return (_rep->isPeerVerificationEnabled());
|
1270 h.sterling 1.26 }
|
1271 kumpf 1.1
|
1272 h.sterling 1.28 SSLCertificateVerifyFunction* SSLContext::getSSLCertificateVerifyFunction() const
1273 {
1274 return (_rep->getSSLCertificateVerifyFunction());
1275 }
1276
|
1277 kumpf 1.1 ///////////////////////////////////////////////////////////////////////////////
1278 //
|
1279 kumpf 1.9 // SSLCertificateInfo
|
1280 kumpf 1.1 //
1281 ///////////////////////////////////////////////////////////////////////////////
|
1282 kumpf 1.16 //
1283 // Certificate validation result codes.
1284 //
1285 const int SSLCertificateInfo::V_OK = 0;
1286
1287 const int SSLCertificateInfo::V_ERR_UNABLE_TO_GET_ISSUER_CERT = 2;
1288 const int SSLCertificateInfo::V_ERR_UNABLE_TO_GET_CRL = 3;
1289 const int SSLCertificateInfo::V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE = 4;
1290 const int SSLCertificateInfo::V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE = 5;
1291 const int SSLCertificateInfo::V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY = 6;
1292 const int SSLCertificateInfo::V_ERR_CERT_SIGNATURE_FAILURE = 7;
1293 const int SSLCertificateInfo::V_ERR_CRL_SIGNATURE_FAILURE = 8;
1294 const int SSLCertificateInfo::V_ERR_CERT_NOT_YET_VALID = 9;
1295 const int SSLCertificateInfo::V_ERR_CERT_HAS_EXPIRED = 10;
1296 const int SSLCertificateInfo::V_ERR_CRL_NOT_YET_VALID = 11;
1297 const int SSLCertificateInfo::V_ERR_CRL_HAS_EXPIRED = 12;
1298 const int SSLCertificateInfo::V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD = 13;
1299 const int SSLCertificateInfo::V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD = 14;
1300 const int SSLCertificateInfo::V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD = 15;
1301 const int SSLCertificateInfo::V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD = 16;
1302 const int SSLCertificateInfo::V_ERR_OUT_OF_MEM = 17;
1303 kumpf 1.16 const int SSLCertificateInfo::V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT = 18;
1304 const int SSLCertificateInfo::V_ERR_SELF_SIGNED_CERT_IN_CHAIN = 19;
1305 const int SSLCertificateInfo::V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY = 20;
1306 const int SSLCertificateInfo::V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE = 21;
1307 const int SSLCertificateInfo::V_ERR_CERT_CHAIN_TOO_LONG = 22;
1308 const int SSLCertificateInfo::V_ERR_CERT_REVOKED = 23;
1309 const int SSLCertificateInfo::V_ERR_INVALID_CA = 24;
1310 const int SSLCertificateInfo::V_ERR_PATH_LENGTH_EXCEEDED = 25;
1311 const int SSLCertificateInfo::V_ERR_INVALID_PURPOSE = 26;
1312 const int SSLCertificateInfo::V_ERR_CERT_UNTRUSTED = 27;
1313 const int SSLCertificateInfo::V_ERR_CERT_REJECTED = 28;
1314 const int SSLCertificateInfo::V_ERR_SUBJECT_ISSUER_MISMATCH = 29;
1315 const int SSLCertificateInfo::V_ERR_AKID_SKID_MISMATCH = 30;
1316 const int SSLCertificateInfo::V_ERR_AKID_ISSUER_SERIAL_MISMATCH = 31;
1317 const int SSLCertificateInfo::V_ERR_KEYUSAGE_NO_CERTSIGN = 32;
1318
1319 const int SSLCertificateInfo::V_ERR_APPLICATION_VERIFICATION = 50;
|
1320 kumpf 1.1
|
1321 kumpf 1.9 class SSLCertificateInfoRep
1322 {
1323 public:
|
1324 kumpf 1.16 String subjectName;
1325 String issuerName;
1326 Uint32 depth;
1327 Uint32 errorCode;
1328 Uint32 respCode;
1329 String errorString;
1330 Uint32 versionNumber;
1331 long serialNumber;
1332 CIMDateTime notBefore;
1333 CIMDateTime notAfter;
|
1334 kumpf 1.9 };
1335
1336
1337 SSLCertificateInfo::SSLCertificateInfo(
|
1338 kumpf 1.1 const String subjectName,
1339 const String issuerName,
1340 const int errorDepth,
|
1341 kumpf 1.14 const int errorCode,
1342 const int respCode)
|
1343 kumpf 1.1 {
|
1344 kumpf 1.9 _rep = new SSLCertificateInfoRep();
1345 _rep->subjectName = subjectName;
1346 _rep->issuerName = issuerName;
|
1347 kumpf 1.16 _rep->versionNumber = 0;
1348 _rep->serialNumber = 0;
|
1349 h.sterling 1.26 _rep->notBefore = CIMDateTime();
1350 _rep->notAfter = CIMDateTime();
|
1351 kumpf 1.16 _rep->depth = errorDepth;
|
1352 kumpf 1.9 _rep->errorCode = errorCode;
|
1353 kumpf 1.16 _rep->errorString = String::EMPTY;
1354 _rep->respCode = respCode;
1355 }
1356
1357 SSLCertificateInfo::SSLCertificateInfo(
1358 const String subjectName,
1359 const String issuerName,
1360 const Uint32 versionNumber,
1361 const long serialNumber,
1362 const CIMDateTime notBefore,
1363 const CIMDateTime notAfter,
1364 const Uint32 depth,
1365 const Uint32 errorCode,
1366 const String errorString,
1367 const Uint32 respCode)
1368 {
1369 _rep = new SSLCertificateInfoRep();
1370 _rep->subjectName = subjectName;
1371 _rep->issuerName = issuerName;
1372 _rep->versionNumber = versionNumber;
1373 _rep->serialNumber = serialNumber;
1374 kumpf 1.16 _rep->notBefore = notBefore;
1375 _rep->notAfter = notAfter;
1376 _rep->depth = depth;
1377 _rep->errorCode = errorCode;
1378 _rep->errorString = errorString;
|
1379 kumpf 1.14 _rep->respCode = respCode;
|
1380 kumpf 1.9 }
1381
1382 SSLCertificateInfo::SSLCertificateInfo(
1383 const SSLCertificateInfo& certificateInfo)
1384 {
1385 _rep = new SSLCertificateInfoRep();
1386 _rep->subjectName = certificateInfo._rep->subjectName;
1387 _rep->issuerName = certificateInfo._rep->issuerName;
|
1388 kumpf 1.16 _rep->versionNumber = certificateInfo._rep->versionNumber;
1389 _rep->serialNumber = certificateInfo._rep->serialNumber;
1390 _rep->notBefore = certificateInfo._rep->notBefore;
1391 _rep->notAfter = certificateInfo._rep->notAfter;
1392 _rep->depth = certificateInfo._rep->depth;
|
1393 kumpf 1.9 _rep->errorCode = certificateInfo._rep->errorCode;
|
1394 kumpf 1.16 _rep->errorString = certificateInfo._rep->errorString;
|
1395 kumpf 1.9 _rep->respCode = certificateInfo._rep->respCode;
|
1396 kumpf 1.11 }
1397
1398 // Dummy constructor made private to disallow default construction
1399 SSLCertificateInfo::SSLCertificateInfo()
1400 {
|
1401 kumpf 1.1 }
1402
|
1403 kumpf 1.9 SSLCertificateInfo::~SSLCertificateInfo()
|
1404 kumpf 1.1 {
|
1405 kumpf 1.9 delete _rep;
|
1406 kumpf 1.1 }
1407
|
1408 kumpf 1.9 String SSLCertificateInfo::getSubjectName() const
|
1409 kumpf 1.1 {
|
1410 kumpf 1.9 return (_rep->subjectName);
|
1411 kumpf 1.1 }
1412
|
1413 kumpf 1.9 String SSLCertificateInfo::getIssuerName() const
|
1414 kumpf 1.1 {
|
1415 kumpf 1.9 return (_rep->issuerName);
|
1416 kumpf 1.1 }
1417
|
1418 kumpf 1.16 Uint32 SSLCertificateInfo::getVersionNumber() const
1419 {
1420 return (_rep->versionNumber);
1421 }
1422
1423 long SSLCertificateInfo::getSerialNumber() const
|
1424 kumpf 1.1 {
|
1425 kumpf 1.16 return (_rep->serialNumber);
|
1426 kumpf 1.1 }
1427
|
1428 kumpf 1.16 CIMDateTime SSLCertificateInfo::getNotBefore() const
1429 {
1430 return (_rep->notBefore);
1431 }
1432
1433 CIMDateTime SSLCertificateInfo::getNotAfter() const
1434 {
1435 return (_rep->notAfter);
1436 }
1437
1438 Uint32 SSLCertificateInfo::getErrorDepth() const
1439 {
1440 return (_rep->depth);
1441 }
1442
1443 Uint32 SSLCertificateInfo::getErrorCode() const
|
1444 kumpf 1.1 {
|
1445 kumpf 1.9 return (_rep->errorCode);
|
1446 kumpf 1.14 }
1447
|
1448 kumpf 1.16 void SSLCertificateInfo::setErrorCode(const int errorCode)
1449 {
1450 _rep->errorCode = errorCode;
1451 }
1452
1453 String SSLCertificateInfo::getErrorString() const
1454 {
1455 return (_rep->errorString);
1456 }
1457
1458 Uint32 SSLCertificateInfo::getResponseCode() const
|
1459 kumpf 1.14 {
1460 return (_rep->respCode);
|
1461 kumpf 1.1 }
1462
|
1463 kumpf 1.9 void SSLCertificateInfo::setResponseCode(const int respCode)
|
1464 kumpf 1.1 {
|
1465 kumpf 1.9 _rep->respCode = respCode;
|
1466 kumpf 1.1 }
1467
|
1468 h.sterling 1.28 String SSLCertificateInfo::toString() const
1469 {
1470 char buf[1024];
1471
1472 String s;
1473
1474 s.append("Subject Name:\n\t");
1475 s.append(_rep->subjectName);
1476 s.append("\n");
1477
1478 s.append("Issuer Name:\n\t");
1479 s.append(_rep->issuerName);
1480 s.append("\n");
1481
1482 sprintf(buf, "Depth: %d\n", _rep->depth);
1483 s.append(buf);
1484
1485 sprintf(buf, "Error code: %d\n", _rep->errorCode);
1486 s.append(buf);
1487
1488 sprintf(buf, "Response (preverify) code: %d\n", _rep->respCode);
1489 h.sterling 1.28 s.append(buf);
1490
1491 s.append("Error string: ");
1492 s.append(_rep->errorString);
1493 s.append("\n");
1494
1495 sprintf(buf, "Version number: %d\n", _rep->versionNumber);
1496 s.append(buf);
1497
1498 sprintf(buf, "Serial number: %ld\n", _rep->serialNumber);
1499 s.append(buf);
1500
1501 s.append("Not before date: ");
1502 s.append((_rep->notBefore).toString());
1503 s.append("\n");
1504
1505 s.append("Not after date: ");
1506 s.append((_rep->notAfter).toString());
1507 s.append("\n");
1508
1509 return s;
1510 h.sterling 1.28 }
1511
|
1512 h.sterling 1.40 SSLCallbackInfo::SSLCallbackInfo(SSLCertificateVerifyFunction* verifyCert, X509_STORE* crlStore)
|
1513 h.sterling 1.28 {
1514 verifyCertificateCallback = verifyCert;
|
1515 h.sterling 1.47 _crlStore = crlStore;
|
1516 h.sterling 1.28 _peerCertificate = NULL;
1517 }
1518
1519 SSLCallbackInfo::~SSLCallbackInfo()
1520 {
1521 if (_peerCertificate)
1522 {
1523 delete _peerCertificate;
1524 }
1525 }
1526
|
1527 kumpf 1.1 PEGASUS_NAMESPACE_END
1528
|