1 karl 1.23 //%2003////////////////////////////////////////////////////////////////////////
|
2 kumpf 1.1 //
|
3 karl 1.23 // 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 // IBM Corp.; EMC Corporation, The Open Group.
|
7 kumpf 1.1 //
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
|
9 kumpf 1.2 // of this software and associated documentation files (the "Software"), to
10 // deal in the Software without restriction, including without limitation the
11 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
12 kumpf 1.1 // sell copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
14 //
|
15 kumpf 1.2 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
|
16 kumpf 1.1 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
17 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
18 kumpf 1.2 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
19 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
21 kumpf 1.1 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 //
24 //==============================================================================
25 //
26 // Author: Markus Mueller (sedgewick_de@yahoo.de)
27 //
|
28 kumpf 1.9 // Modified By: Nag Boranna, Hewlett-Packard Company (nagaraja_boranna@hp.com)
29 // Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com)
|
30 kumpf 1.15 // Sushma Fernandes,
31 // Hewlett-Packard Company (sushma_fernandes@hp.com)
|
32 kumpf 1.1 //
33 //%/////////////////////////////////////////////////////////////////////////////
34
35 #ifdef PEGASUS_HAS_SSL
|
36 mday 1.19 #define OPENSSL_NO_KRB5 1
|
37 kumpf 1.1 #include <openssl/err.h>
38 #include <openssl/ssl.h>
39 #include <openssl/rand.h>
40 #else
41 #define SSL_CTX void
42 #endif // end of PEGASUS_HAS_SSL
43 #include <Pegasus/Common/Destroyer.h>
44 #include <Pegasus/Common/Socket.h>
45 #include <Pegasus/Common/Tracer.h>
|
46 kumpf 1.14 #include <Pegasus/Common/FileSystem.h>
|
47 kumpf 1.16 #include <time.h>
|
48 humberto 1.18 #include <Pegasus/Common/MessageLoader.h> //l10n
|
49 kumpf 1.1
50 #include "SSLContext.h"
51 #include "SSLContextRep.h"
52
|
53 kumpf 1.16 typedef struct Timestamp
54 {
55 char year[4];
56 char month[2];
57 char day[2];
58 char hour[2];
59 char minutes[2];
60 char seconds[2];
61 char dot;
62 char microSeconds[6];
63 char plusOrMinus;
64 char utcOffset[3];
65 char padding[3];
66 } Timestamp_t;
67
|
68 kumpf 1.1 PEGASUS_USING_STD;
69
70 PEGASUS_NAMESPACE_BEGIN
71
72 //
73 // use the following definitions only if SSL is available
74 //
|
75 kumpf 1.3 #ifdef PEGASUS_HAS_SSL
|
76 kumpf 1.1
77 //
78 // certificate handling routine
79 //
80
|
81 kumpf 1.9 // ATTN-RK-20020905: This global variable is unsafe with multiple SSL contexts
82 SSLCertificateVerifyFunction* verify_certificate;
|
83 kumpf 1.1
|
84 kumpf 1.15 // Mutex for SSL locks.
85 Mutex* SSLContextRep::_sslLocks = 0;
86
87 // Mutex for _countRep.
88 Mutex SSLContextRep::_countRepMutex;
89
90 // Initialise _count for SSLContextRep objects.
91 int SSLContextRep::_countRep = 0;
92
|
93 kumpf 1.16
94 //
95 // Convert ASN1_UTCTIME to CIMDateTime
96 //
97 CIMDateTime getDateTime(const ASN1_UTCTIME *utcTime)
98 {
99 struct tm time;
100 int offset;
101 Timestamp_t timeStamp;
102 char tempString[80];
103 char plusOrMinus = '+';
104
105 memset(&time, '\0', sizeof(time));
106
107 #define g2(p) ( ( (p)[0] - '0' ) * 10 + (p)[1] - '0' )
108
109 time.tm_year = g2(utcTime->data);
110
111 if(time.tm_year < 50)
112 {
113 time.tm_year += 100;
114 kumpf 1.16 }
115 time.tm_mon = g2(utcTime->data + 2) - 1;
116 time.tm_mday = g2(utcTime->data + 4);
117 time.tm_hour = g2(utcTime->data + 6);
118 time.tm_min = g2(utcTime->data + 8);
119 time.tm_sec = g2(utcTime->data + 10);
120
121 if(utcTime->data[12] == 'Z')
122 {
123 offset = 0;
124 }
125 else
126 {
127 offset = g2(utcTime->data + 13) * 60 + g2(utcTime->data + 15);
128 if(utcTime->data[12] == '-')
129 {
130 plusOrMinus = '-';
131 }
132 }
133 #undef g2
134
135 kumpf 1.16 int year = 1900;
136 memset((void *)&timeStamp, 0, sizeof(Timestamp_t));
137
138 // Format the date.
139 sprintf((char *) &timeStamp,"%04d%02d%02d%02d%02d%02d.%06d%04d",
140 year + time.tm_year,
141 time.tm_mon + 1,
142 time.tm_mday,
143 time.tm_hour,
144 time.tm_min,
145 time.tm_sec,
146 0,
147 offset);
148
149 timeStamp.plusOrMinus = plusOrMinus;
150
151 CIMDateTime dateTime;
152
153 dateTime.clear();
154 strcpy(tempString, (char *)&timeStamp);
155 dateTime.set(tempString);
156 kumpf 1.16
157 return (dateTime);
158 }
159
160 //
161 // Callback function that is called by the OpenSSL library. This function
162 // extracts X509 certficate information and pass that on to client application
163 // callback function.
164 //
165 int prepareForCallback(int preVerifyOk, X509_STORE_CTX *ctx)
|
166 kumpf 1.1 {
|
167 kumpf 1.3 PEG_METHOD_ENTER(TRC_SSL, "prepareForCallback()");
|
168 kumpf 1.1
169 char buf[256];
|
170 kumpf 1.16 X509 *currentCert;
171 int verifyError = X509_V_OK;
|
172 kumpf 1.1
|
173 kumpf 1.16 //
174 // get the current certificate
175 //
176 currentCert = X509_STORE_CTX_get_current_cert(ctx);
|
177 kumpf 1.1
|
178 kumpf 1.16 //
179 // get the default verification error code
180 //
181 int errorCode = X509_STORE_CTX_get_error(ctx);
182
183 //
184 // get the depth of certificate chain
185 //
186 int depth = X509_STORE_CTX_get_error_depth(ctx);
|
187 kumpf 1.1
188 //FUTURE: Not sure what to do with these...?
189 //ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
190 //mydata = SSL_get_ex_data(ssl, mydata_index);
191
|
192 kumpf 1.16 //
193 // get the version on the certificate
194 //
195 long version = X509_get_version(currentCert);
|
196 kumpf 1.1
|
197 kumpf 1.16 //
198 // get the serial number of the certificate
199 //
200 long serialNumber = ASN1_INTEGER_get(X509_get_serialNumber(currentCert));
201
202 //
203 // get the validity of the certificate
204 //
205 CIMDateTime notBefore = getDateTime(X509_get_notBefore(currentCert));
206
207 CIMDateTime notAfter = getDateTime(X509_get_notAfter(currentCert));
208
209 //
210 // get the subject name on the certificate
211 //
212 X509_NAME_oneline(X509_get_subject_name(currentCert), buf, 256);
213 String subjectName = String(buf);
214
215 //
216 // get the default verification error string
217 //
218 kumpf 1.16 String errorStr = String(X509_verify_cert_error_string(errorCode));
|
219 kumpf 1.1
|
220 kumpf 1.16 //
221 // log the error string if the default verification was failed
222 //
223 if (!preVerifyOk)
|
224 kumpf 1.1 {
|
225 kumpf 1.3 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,
|
226 kumpf 1.16 "---> SSL: certificate default verification error: " + errorStr);
|
227 kumpf 1.1 }
228
|
229 kumpf 1.16 //
230 // get the issuer name on the certificate
231 //
232 if (!preVerifyOk && (errorCode == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT))
|
233 kumpf 1.1 {
234 X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256);
235 }
236 else
237 {
|
238 kumpf 1.16 X509_NAME_oneline(X509_get_issuer_name(currentCert), buf, 256);
|
239 kumpf 1.1 }
|
240 kumpf 1.16 String issuerName = String(buf);
|
241 kumpf 1.1
242 //
|
243 kumpf 1.16 // Call the verify_certificate() application callback
|
244 kumpf 1.1 //
|
245 kumpf 1.16 SSLCertificateInfo certInfo(subjectName, issuerName, version, serialNumber,
246 notBefore, notAfter, depth, errorCode, errorStr, preVerifyOk);
|
247 kumpf 1.1
248 if (verify_certificate(certInfo))
249 {
|
250 kumpf 1.16 verifyError = X509_V_OK;
251 preVerifyOk = 1;
252 Tracer::trace(TRC_SSL, Tracer::LEVEL4,
253 "--> SSL: verify_certificate() returned X509_V_OK");
254 }
255 else
256 {
257 verifyError = certInfo.getErrorCode();
258 preVerifyOk = 0;
259 Tracer::trace(TRC_SSL, Tracer::LEVEL4,
260 "--> SSL: verify_certificate() returned error %d", verifyError);
|
261 kumpf 1.1 }
262
|
263 kumpf 1.16 //
264 // Reset the error. It is logically not required to reset the error code, but
265 // openSSL code does not take just the return value on a failed certificate
266 // verification.
267 //
268 X509_STORE_CTX_set_error(ctx, verifyError);
269
|
270 kumpf 1.1 PEG_METHOD_EXIT();
|
271 kumpf 1.16
272 return(preVerifyOk);
|
273 kumpf 1.1 }
274
|
275 kumpf 1.15 //
276 // Implement OpenSSL locking callback.
277 //
278 void pegasus_locking_callback( int mode,
279 int type,
280 const char* file,
281 int line)
282 {
283 // Check whether the mode is lock or unlock.
284
285 if ( mode & CRYPTO_LOCK )
286 {
287 Tracer::trace(TRC_SSL, Tracer::LEVEL4,
288 "Now locking for %d", pegasus_thread_self());
289 SSLContextRep::_sslLocks[type].lock( pegasus_thread_self() );
290 }
291 else
292 {
293 Tracer::trace(TRC_SSL, Tracer::LEVEL4,
294 "Now unlocking for %d", pegasus_thread_self());
295 SSLContextRep::_sslLocks[type].unlock( );
296 kumpf 1.15 }
297 }
298
299 //
300 // Initialize OpenSSL Locking and id callbacks.
301 //
302 void SSLContextRep::init_ssl()
303 {
304 // Allocate Memory for _sslLocks. SSL locks needs to be able to handle
305 // up to CRYPTO_num_locks() different mutex locks.
306 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,
307 "Initialized SSL callback.");
308
309 _sslLocks= new Mutex[CRYPTO_num_locks()];
310
311 // Set the ID callback. The ID callback returns a thread ID.
312
313 CRYPTO_set_id_callback((unsigned long (*)())pegasus_thread_self);
314
315 // Set the locking callback to pegasus_locking_callback.
316
317 kumpf 1.15 CRYPTO_set_locking_callback((void (*)(int,int,const char *,int))pegasus_locking_callback);
318
319 }
320
321 // Free OpenSSL Locking and id callbacks.
322 void SSLContextRep::free_ssl()
323 {
324 // Cleanup _sslLocks and set locking & id callback to NULL.
325
326 CRYPTO_set_locking_callback(NULL);
327 CRYPTO_set_id_callback (NULL);
328 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,
329 "Freed SSL callback.");
330
331 delete []_sslLocks;
332 }
333
|
334 kumpf 1.1
335 //
336 // SSL context area
337 //
338 // For the OSs that don't have /dev/random device file,
339 // must enable PEGASUS_SSL_RANDOMFILE flag.
340 //
|
341 kumpf 1.16 SSLContextRep::SSLContextRep(const String& trustPath,
342 const String& certPath,
343 const String& keyPath,
|
344 kumpf 1.9 SSLCertificateVerifyFunction* verifyCert,
|
345 kumpf 1.13 const String& randomFile)
|
346 kumpf 1.1 {
|
347 kumpf 1.3 PEG_METHOD_ENTER(TRC_SSL, "SSLContextRep::SSLContextRep()");
|
348 kumpf 1.1
|
349 kumpf 1.16 _trustPath = trustPath.getCString();
350
|
351 kumpf 1.7 _certPath = certPath.getCString();
|
352 kumpf 1.1
|
353 kumpf 1.16 _keyPath = keyPath.getCString();
|
354 kumpf 1.14
|
355 kumpf 1.1 verify_certificate = verifyCert;
356
|
357 kumpf 1.15
358 // Initialiaze SSL callbacks and increment the SSLContextRep object _counter.
359 _countRepMutex.lock(pegasus_thread_self());
360
361 try
362 {
363 Tracer::trace(TRC_SSL, Tracer::LEVEL4,
364 "Value of Countrep in constructor %d", _countRep);
365 if ( _countRep == 0 )
366 {
367 init_ssl();
368
369 //
370 // load SSL library
371 //
372 Tracer::trace(TRC_SSL, Tracer::LEVEL4,
373 "Before calling SSL_load_error_strings %d", pegasus_thread_self());
374
375 SSL_load_error_strings();
376
377 Tracer::trace(TRC_SSL, Tracer::LEVEL4,
378 kumpf 1.15 "After calling SSL_load_error_strings %d", pegasus_thread_self());
379
380 Tracer::trace(TRC_SSL, Tracer::LEVEL4,
381 "Before calling SSL_library_init %d", pegasus_thread_self());
382
383 SSL_library_init();
384
385 Tracer::trace(TRC_SSL, Tracer::LEVEL4,
386 "After calling SSL_library_init %d", pegasus_thread_self());
387
388 }
389 }
390 catch(...)
391 {
392 _countRepMutex.unlock();
393 throw;
394 }
395 _countRep++;
396 _countRepMutex.unlock();
|
397 kumpf 1.1
|
398 kumpf 1.14 _randomInit(randomFile);
|
399 kumpf 1.1
|
400 kumpf 1.9 _sslContext = _makeSSLContext();
401
402 PEG_METHOD_EXIT();
403 }
404
405 SSLContextRep::SSLContextRep(const SSLContextRep& sslContextRep)
406 {
407 PEG_METHOD_ENTER(TRC_SSL, "SSLContextRep::SSLContextRep()");
408
|
409 kumpf 1.16 _trustPath = sslContextRep._trustPath;
|
410 kumpf 1.9 _certPath = sslContextRep._certPath;
|
411 kumpf 1.16 _keyPath = sslContextRep._keyPath;
|
412 kumpf 1.9 // ATTN: verify_certificate is set implicitly in global variable
413 _randomFile = sslContextRep._randomFile;
|
414 kumpf 1.15
415 // Initialiaze SSL callbacks and increment the SSLContextRep object _counter.
416 _countRepMutex.lock(pegasus_thread_self());
417 try
418 {
419 Tracer::trace(TRC_SSL, Tracer::LEVEL4,
420 "Value of Countrep in copy constructor %d", _countRep);
421 if ( _countRep == 0 )
422 {
423 init_ssl();
424 }
425 }
426 catch(...)
427 {
428 _countRepMutex.unlock();
429 throw;
430 }
431 _countRep++;
432 _countRepMutex.unlock();
433
|
434 kumpf 1.9 _sslContext = _makeSSLContext();
435 PEG_METHOD_EXIT();
436 }
|
437 kumpf 1.11
|
438 kumpf 1.9 //
439 // Destructor
440 //
441
442 SSLContextRep::~SSLContextRep()
443 {
444 PEG_METHOD_ENTER(TRC_SSL, "SSLContextRep::~SSLContextRep()");
445
446 SSL_CTX_free(_sslContext);
447
|
448 kumpf 1.15 // Decrement the SSLContextRep object _counter.
449 _countRepMutex.lock(pegasus_thread_self());
450 _countRep--;
451 // Free SSL locks if no instances of SSLContextRep exist.
452 try
453 {
454 Tracer::trace(TRC_SSL, Tracer::LEVEL4,
455 "Value of Countrep in destructor %d", _countRep);
456 if ( _countRep == 0 )
457 {
458 free_ssl();
459 }
460 }
461 catch(...)
462 {
463 _countRepMutex.unlock();
464 throw;
465 }
466 _countRepMutex.unlock();
|
467 kumpf 1.9 PEG_METHOD_EXIT();
468 }
469
|
470 kumpf 1.14 //
471 // initialize OpenSSL's PRNG
472 //
473 void SSLContextRep::_randomInit(const String& randomFile)
474 {
475 PEG_METHOD_ENTER(TRC_SSL, "SSLContextRep::_randomInit()");
476
477 Boolean ret;
478 int retVal = 0;
479
|
480 kumpf 1.15 const int DEV_RANDOM_BYTES = 64; /* how many bytes to read */
|
481 kumpf 1.14 const String devRandom = "/dev/random"; /* random device name */
482 const String devUrandom = "/dev/urandom"; /* pseudo-random device name */
483
484 #ifdef PEGASUS_SSL_DEVRANDOM
485
486 if ( FileSystem::exists(devRandom) )
487 {
488 while ( RAND_status() == 0 )
489 {
490 //
|
491 kumpf 1.15 // Always attempt to seed from good entropy sources, first
|
492 kumpf 1.14 // try /dev/random
493 //
494 retVal = RAND_load_file(devRandom.getCString(), DEV_RANDOM_BYTES);
|
495 kumpf 1.15 if (retVal <= 0)
|
496 kumpf 1.14 {
497 break;
498 }
499 }
500 }
501
502 if ( FileSystem::exists(devUrandom) )
503 {
504 while ( RAND_status() == 0 )
505 {
506 //
507 // If there isn't /dev/random try /dev/urandom
508 //
509 retVal = RAND_load_file(devUrandom.getCString(), DEV_RANDOM_BYTES);
|
510 kumpf 1.15 if (retVal <= 0)
|
511 kumpf 1.14 {
512 break;
513 }
514 }
515 }
516 #endif /* PEGASUS_SSL_DEVRANDOM */
517
518
519 #ifdef PEGASUS_SSL_RANDOMFILE
520 if ( RAND_status() == 0 )
521 {
522 //
523 // Initialise OpenSSL random number generator.
524 //
525 if ( randomFile == String::EMPTY )
526 {
527 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,
528 "Random seed file is required.");
529 PEG_METHOD_EXIT();
|
530 humberto 1.18 //l10n
531 //throw( SSLException("Random seed file required"));
532 MessageLoaderParms parms("Common.SSLContext.RANDOM_SEED_FILE_REQUIRED",
533 "Random seed file required");
534 throw( SSLException(parms));
|
535 kumpf 1.14 }
536
537 //
538 // Try the given random seed file
539 //
540 ret = FileSystem::exists(randomFile);
541 if( ret )
542 {
|
543 kumpf 1.15 retVal = RAND_load_file(randomFile.getCString(), -1);
|
544 kumpf 1.14 if ( retVal < 0 )
545 {
546 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,
547 "Not enough seed data in seed file: " + randomFile);
548 PEG_METHOD_EXIT();
|
549 humberto 1.18 //l10n
|
550 humberto 1.22 // do not put in $0 in default message, but pass in filename for bundle message
|
551 humberto 1.18 //throw( SSLException("Not enough seed data in random seed file."));
552 MessageLoaderParms parms("Common.SSLContext.NOT_ENOUGH_SEED_DATA_IN_FILE",
|
553 humberto 1.21 "Not enough seed data in random seed file.",
554 randomFile);
|
555 humberto 1.18 throw( SSLException(parms));
|
556 kumpf 1.14 }
557 }
|
558 kumpf 1.16 else
559 {
560 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,
561 "seed file - " + randomFile + " does not exist.");
562 PEG_METHOD_EXIT();
|
563 humberto 1.18 //l10n
564 //throw( SSLException("Seed file '" + randomFile + "' does not exist."));
565 MessageLoaderParms parms("Common.SSLContext.SEED_FILE_DOES_NOT_EXIST",
566 "Seed file '$0' does not exist.",
567 randomFile);
568 throw( SSLException(parms));
|
569 kumpf 1.16 }
|
570 kumpf 1.14
571 if ( RAND_status() == 0 )
572 {
573 //
574 // Try to do more seeding
575 //
576 long seedNumber;
577 srandom((unsigned int)time(NULL)); // Initialize
578 seedNumber = random();
579 RAND_seed((unsigned char *) &seedNumber, sizeof(seedNumber));
580
581 int seedRet = RAND_status();
582 if ( seedRet == 0 )
583 {
584 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,
|
585 kumpf 1.15 "Not enough seed data in random seed file, RAND_status = " +
586 seedRet);
|
587 kumpf 1.14 PEG_METHOD_EXIT();
|
588 humberto 1.22 //l10n 485
589 // do not put in $0 in default message, but pass in filename for bundle message
|
590 humberto 1.18 //throw( SSLException("Not enough seed data in random seed file."));
591 MessageLoaderParms parms("Common.SSLContext.NOT_ENOUGH_SEED_DATA_IN_FILE",
|
592 humberto 1.22 "Not enough seed data in random seed file.",
593 randomFile);
|
594 humberto 1.18 throw( SSLException(parms));
|
595 kumpf 1.14 }
596 }
597 }
598 #endif /* PEGASUS_SSL_RANDOMFILE */
599
600 int seedRet = RAND_status();
601 if ( seedRet == 0 )
602 {
603 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,
604 "Not enough seed data , RAND_status = " + seedRet );
605 PEG_METHOD_EXIT();
|
606 humberto 1.18 //l10n
607 //throw( SSLException("Not enough seed data."));
608 MessageLoaderParms parms("Common.SSLContext.NOT_ENOUGH_SEED_DATA",
609 "Not enough seed data.");
610 throw( SSLException(parms));
|
611 kumpf 1.14 }
612
613 PEG_METHOD_EXIT();
614 }
615
|
616 kumpf 1.9 SSL_CTX * SSLContextRep::_makeSSLContext()
617 {
618 PEG_METHOD_ENTER(TRC_SSL, "SSLContextRep::_makeSSLContext()");
619
620 SSL_CTX * sslContext = 0;
621
|
622 kumpf 1.1 //
623 // create SSL Context Area
624 //
625
|
626 kumpf 1.9 if (!( sslContext = SSL_CTX_new(SSLv23_method()) ))
|
627 kumpf 1.3 {
628 PEG_METHOD_EXIT();
|
629 humberto 1.18 //l10n
630 //throw( SSLException("Could not get SSL CTX"));
631 MessageLoaderParms parms("Common.SSLContext.COULD_NOT_GET",
|
632 humberto 1.20 "Could not get SSL CTX");
|
633 humberto 1.18 throw( SSLException(parms));
|
634 kumpf 1.3 }
635
|
636 kumpf 1.14 #ifdef PEGASUS_SSL_WEAKENCRYPTION
|
637 humberto 1.18 if (!(SSL_CTX_set_cipher_list(sslContext, SSL_TXT_EXP40))){
638 //l10n
639 //throw( SSLException("Could not set the cipher list"));
640 MessageLoaderParms parms("Common.SSLContext.COULD_NOT_SET_CIPHER_LIST",
641 "Could not set the cipher list");
642 throw( SSLException(parms));
643 }
|
644 kumpf 1.3 #endif
|
645 kumpf 1.1
646 //
647 // set overall SSL Context flags
648 //
649
|
650 kumpf 1.9 SSL_CTX_set_quiet_shutdown(sslContext, 1);
651 SSL_CTX_set_mode(sslContext, SSL_MODE_AUTO_RETRY);
652 SSL_CTX_set_options(sslContext,SSL_OP_ALL);
|
653 kumpf 1.14 SSL_CTX_set_session_cache_mode(sslContext, SSL_SESS_CACHE_OFF);
|
654 kumpf 1.1
|
655 kumpf 1.10 if (verify_certificate != NULL)
|
656 kumpf 1.1 {
|
657 kumpf 1.9 SSL_CTX_set_verify(sslContext,
|
658 kumpf 1.16 SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, prepareForCallback);
|
659 kumpf 1.1 }
|
660 kumpf 1.14 else
661 {
|
662 kumpf 1.15 SSL_CTX_set_verify(sslContext, SSL_VERIFY_NONE, NULL);
|
663 kumpf 1.14 }
|
664 kumpf 1.1
665 //
|
666 kumpf 1.14 // Check if there is CA certificate file specified. If specified,
667 // load the certificates from the file in to the CA trust store.
668 //
|
669 kumpf 1.16 if (strncmp(_trustPath, "", 1) != 0)
|
670 kumpf 1.14 {
671 //
672 // load certificates in to trust store
673 //
674
|
675 kumpf 1.16 if ((!SSL_CTX_load_verify_locations(sslContext, _trustPath, NULL)) ||
|
676 kumpf 1.14 (!SSL_CTX_set_default_verify_paths(sslContext)))
677 {
678 PEG_METHOD_EXIT();
|
679 humberto 1.18 //l10n
680 //throw( SSLException("Could not load certificates in to trust store."));
681 MessageLoaderParms parms("Common.SSLContext.COULD_NOT_LOAD_CERTIFICATES",
682 "Could not load certificates in to trust store.");
683 throw( SSLException(parms));
|
684 kumpf 1.14 }
685 }
686
|
687 kumpf 1.17 Boolean keyLoaded = false;
|
688 kumpf 1.1 //
|
689 kumpf 1.16 // Check if there is a certificate file (file containing server
690 // certificate) specified. If specified, validate and load the
691 // certificate.
|
692 kumpf 1.14 //
|
693 kumpf 1.16 if (strncmp(_certPath, "", 1) != 0)
|
694 kumpf 1.14 {
695 //
696 // load the specified server certificates
697 //
|
698 kumpf 1.1
|
699 kumpf 1.14 if (SSL_CTX_use_certificate_file(sslContext,
|
700 kumpf 1.16 _certPath, SSL_FILETYPE_PEM) <=0)
|
701 kumpf 1.14 {
702 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,
|
703 kumpf 1.16 "---> SSL: no certificate found in " + String(_certPath));
|
704 kumpf 1.14 PEG_METHOD_EXIT();
|
705 humberto 1.18 //l10n
706 //throw( SSLException("Could not get server certificate."));
707 MessageLoaderParms parms("Common.SSLContext.COULD_NOT_GET_SERVER_CERTIFICATE",
708 "Could not get server certificate.");
709 throw( SSLException(parms));
|
710 kumpf 1.14 }
|
711 kumpf 1.17
|
712 kumpf 1.16 //
713 // If there is no key file (file containing server
|
714 kumpf 1.17 // private key) specified or the specified file does not exist,
715 // then try loading the key from the certificate file.
|
716 kumpf 1.16 //
|
717 kumpf 1.17 if ( strncmp(_keyPath, "", 1) == 0 ||
718 !FileSystem::exists(String(_keyPath)) )
|
719 kumpf 1.16 {
|
720 kumpf 1.17 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL3,
721 "---> SSL: loading key from" + String(_certPath));
|
722 kumpf 1.16 //
723 // load the private key and check for validity
724 //
725 if (!_verifyPrivateKey(sslContext, _certPath))
726 {
727 PEG_METHOD_EXIT();
|
728 humberto 1.18 //l10n
729 //throw( SSLException("Could not get private key."));
730 MessageLoaderParms parms("Common.SSLContext.COULD_NOT_GET_PRIVATE_KEY",
731 "Could not get private key.");
732 throw( SSLException(parms));
|
733 kumpf 1.16 }
|
734 kumpf 1.17 keyLoaded = true;
|
735 kumpf 1.16 }
736 }
|
737 kumpf 1.14
|
738 kumpf 1.16 //
|
739 kumpf 1.17 // Check if there is a key file (file containing server
740 // private key) specified and the key was not already loaded.
741 // If specified, validate and load the key.
|
742 kumpf 1.16 //
|
743 kumpf 1.17 if (strncmp(_keyPath, "", 1) != 0 && !keyLoaded)
|
744 kumpf 1.16 {
|
745 kumpf 1.17 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL3,
746 "---> SSL: loading key from" + String(_keyPath));
|
747 kumpf 1.14 //
748 // load given private key and check for validity
749 //
|
750 kumpf 1.16 if (!_verifyPrivateKey(sslContext, _keyPath))
|
751 kumpf 1.14 {
752 PEG_METHOD_EXIT();
|
753 humberto 1.18 //l10n
754 //throw( SSLException("Could not get private key."));
755 MessageLoaderParms parms("Common.SSLContext.COULD_NOT_GET_PRIVATE_KEY",
756 "Could not get private key.");
757 throw( SSLException(parms));
|
758 kumpf 1.14 }
|
759 kumpf 1.17 keyLoaded = true;
|
760 kumpf 1.14 }
761
762 PEG_METHOD_EXIT();
763 return sslContext;
764 }
765
|
766 kumpf 1.16 Boolean SSLContextRep::_verifyPrivateKey(SSL_CTX *ctx, const char *keyPath)
|
767 kumpf 1.14 {
768 PEG_METHOD_ENTER(TRC_SSL, "_verifyPrivateKey()");
769
|
770 kumpf 1.16 if (SSL_CTX_use_PrivateKey_file(ctx, keyPath, SSL_FILETYPE_PEM) <= 0)
|
771 kumpf 1.3 {
|
772 kumpf 1.14 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,
|
773 kumpf 1.16 "---> SSL: no private key found in " + String(keyPath));
|
774 kumpf 1.3 PEG_METHOD_EXIT();
|
775 kumpf 1.14 return false;
776 }
777
778 if (!SSL_CTX_check_private_key(ctx))
779 {
780 PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4,
781 "---> SSL: Private and public key do not match");
782 PEG_METHOD_EXIT();
783 return false;
|
784 kumpf 1.3 }
|
785 kumpf 1.1
|
786 kumpf 1.3 PEG_METHOD_EXIT();
|
787 kumpf 1.14 return true;
|
788 kumpf 1.1 }
789
790 SSL_CTX * SSLContextRep::getContext() const
791 {
|
792 kumpf 1.9 return _sslContext;
|
793 kumpf 1.1 }
794 #else
795
796 //
|
797 kumpf 1.9 // these definitions are used if ssl is not available
|
798 kumpf 1.1 //
799
|
800 kumpf 1.16 SSLContextRep::SSLContextRep(const String& trustPath,
801 const String& certPath,
802 const String& keyPath,
|
803 kumpf 1.9 SSLCertificateVerifyFunction* verifyCert,
|
804 kumpf 1.13 const String& randomFile) {}
|
805 kumpf 1.1
|
806 kumpf 1.9 SSLContextRep::SSLContextRep(const SSLContextRep& sslContextRep) {}
807
|
808 kumpf 1.1 SSLContextRep::~SSLContextRep() {}
809
|
810 kumpf 1.9 SSL_CTX * SSLContextRep::_makeSSLContext() { return 0; }
811
|
812 kumpf 1.14 Boolean SSLContextRep::_verifyPrivateKey(SSL_CTX *ctx,
|
813 kumpf 1.16 const char *keyPath) { return false; }
|
814 kumpf 1.14
|
815 kumpf 1.9 SSL_CTX * SSLContextRep::getContext() const { return 0; }
|
816 kumpf 1.15
817 void SSLContextRep::init_ssl() {}
818
819 void SSLContextRep::free_ssl() {}
|
820 kumpf 1.1
821 #endif // end of PEGASUS_HAS_SSL
822
823 ///////////////////////////////////////////////////////////////////////////////
824 //
825 // SSLContext
826 //
827 ///////////////////////////////////////////////////////////////////////////////
828
829
830 SSLContext::SSLContext(
|
831 kumpf 1.16 const String& trustPath,
|
832 kumpf 1.9 SSLCertificateVerifyFunction* verifyCert,
|
833 kumpf 1.13 const String& randomFile)
834 {
|
835 kumpf 1.16 _rep = new SSLContextRep(trustPath, String::EMPTY, String::EMPTY, verifyCert, randomFile);
|
836 kumpf 1.13 }
837
838 #ifndef PEGASUS_REMOVE_DEPRECATED
839 SSLContext::SSLContext(
840 const String& certPath,
841 SSLCertificateVerifyFunction* verifyCert,
|
842 kumpf 1.1 const String& randomFile,
|
843 kumpf 1.6 Boolean isCIMClient)
|
844 kumpf 1.1 {
|
845 kumpf 1.16 _rep = new SSLContextRep(certPath, String::EMPTY, String::EMPTY, verifyCert, randomFile);
846 }
847
848 SSLContext::SSLContext(
849 const String& certPath,
850 const String& certKeyPath,
851 SSLCertificateVerifyFunction* verifyCert,
852 const String& randomFile)
853 {
854 _rep = new SSLContextRep(certPath, certKeyPath, String::EMPTY, verifyCert, randomFile);
|
855 kumpf 1.1 }
|
856 kumpf 1.13 #endif
|
857 kumpf 1.1
|
858 kumpf 1.14 SSLContext::SSLContext(
|
859 kumpf 1.16 const String& trustPath,
|
860 kumpf 1.14 const String& certPath,
|
861 kumpf 1.16 const String& keyPath,
|
862 kumpf 1.14 SSLCertificateVerifyFunction* verifyCert,
863 const String& randomFile)
864 {
|
865 kumpf 1.16 _rep = new SSLContextRep(trustPath, certPath, keyPath, verifyCert, randomFile);
|
866 kumpf 1.14 }
867
|
868 kumpf 1.9 SSLContext::SSLContext(const SSLContext& sslContext)
869 {
870 _rep = new SSLContextRep(*sslContext._rep);
|
871 kumpf 1.12 }
872
873 // Dummy constructor made private to disallow default construction
874 SSLContext::SSLContext()
875 {
|
876 kumpf 1.9 }
877
|
878 kumpf 1.1 SSLContext::~SSLContext()
879 {
880 delete _rep;
881 }
882
883
884 ///////////////////////////////////////////////////////////////////////////////
885 //
|
886 kumpf 1.9 // SSLCertificateInfo
|
887 kumpf 1.1 //
888 ///////////////////////////////////////////////////////////////////////////////
|
889 kumpf 1.16 //
890 // Certificate validation result codes.
891 //
892 const int SSLCertificateInfo::V_OK = 0;
893
894 const int SSLCertificateInfo::V_ERR_UNABLE_TO_GET_ISSUER_CERT = 2;
895 const int SSLCertificateInfo::V_ERR_UNABLE_TO_GET_CRL = 3;
896 const int SSLCertificateInfo::V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE = 4;
897 const int SSLCertificateInfo::V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE = 5;
898 const int SSLCertificateInfo::V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY = 6;
899 const int SSLCertificateInfo::V_ERR_CERT_SIGNATURE_FAILURE = 7;
900 const int SSLCertificateInfo::V_ERR_CRL_SIGNATURE_FAILURE = 8;
901 const int SSLCertificateInfo::V_ERR_CERT_NOT_YET_VALID = 9;
902 const int SSLCertificateInfo::V_ERR_CERT_HAS_EXPIRED = 10;
903 const int SSLCertificateInfo::V_ERR_CRL_NOT_YET_VALID = 11;
904 const int SSLCertificateInfo::V_ERR_CRL_HAS_EXPIRED = 12;
905 const int SSLCertificateInfo::V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD = 13;
906 const int SSLCertificateInfo::V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD = 14;
907 const int SSLCertificateInfo::V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD = 15;
908 const int SSLCertificateInfo::V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD = 16;
909 const int SSLCertificateInfo::V_ERR_OUT_OF_MEM = 17;
910 kumpf 1.16 const int SSLCertificateInfo::V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT = 18;
911 const int SSLCertificateInfo::V_ERR_SELF_SIGNED_CERT_IN_CHAIN = 19;
912 const int SSLCertificateInfo::V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY = 20;
913 const int SSLCertificateInfo::V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE = 21;
914 const int SSLCertificateInfo::V_ERR_CERT_CHAIN_TOO_LONG = 22;
915 const int SSLCertificateInfo::V_ERR_CERT_REVOKED = 23;
916 const int SSLCertificateInfo::V_ERR_INVALID_CA = 24;
917 const int SSLCertificateInfo::V_ERR_PATH_LENGTH_EXCEEDED = 25;
918 const int SSLCertificateInfo::V_ERR_INVALID_PURPOSE = 26;
919 const int SSLCertificateInfo::V_ERR_CERT_UNTRUSTED = 27;
920 const int SSLCertificateInfo::V_ERR_CERT_REJECTED = 28;
921 const int SSLCertificateInfo::V_ERR_SUBJECT_ISSUER_MISMATCH = 29;
922 const int SSLCertificateInfo::V_ERR_AKID_SKID_MISMATCH = 30;
923 const int SSLCertificateInfo::V_ERR_AKID_ISSUER_SERIAL_MISMATCH = 31;
924 const int SSLCertificateInfo::V_ERR_KEYUSAGE_NO_CERTSIGN = 32;
925
926 const int SSLCertificateInfo::V_ERR_APPLICATION_VERIFICATION = 50;
|
927 kumpf 1.1
|
928 kumpf 1.9 class SSLCertificateInfoRep
929 {
930 public:
|
931 kumpf 1.16 String subjectName;
932 String issuerName;
933 Uint32 depth;
934 Uint32 errorCode;
935 Uint32 respCode;
936 String errorString;
937 Uint32 versionNumber;
938 long serialNumber;
939 CIMDateTime notBefore;
940 CIMDateTime notAfter;
|
941 kumpf 1.9 };
942
943
944 SSLCertificateInfo::SSLCertificateInfo(
|
945 kumpf 1.1 const String subjectName,
946 const String issuerName,
947 const int errorDepth,
|
948 kumpf 1.14 const int errorCode,
949 const int respCode)
|
950 kumpf 1.1 {
|
951 kumpf 1.9 _rep = new SSLCertificateInfoRep();
952 _rep->subjectName = subjectName;
953 _rep->issuerName = issuerName;
|
954 kumpf 1.16 _rep->versionNumber = 0;
955 _rep->serialNumber = 0;
956 _rep->notBefore = CIMDateTime(String::EMPTY);
957 _rep->notAfter = CIMDateTime(String::EMPTY);
958 _rep->depth = errorDepth;
|
959 kumpf 1.9 _rep->errorCode = errorCode;
|
960 kumpf 1.16 _rep->errorString = String::EMPTY;
961 _rep->respCode = respCode;
962 }
963
964 SSLCertificateInfo::SSLCertificateInfo(
965 const String subjectName,
966 const String issuerName,
967 const Uint32 versionNumber,
968 const long serialNumber,
969 const CIMDateTime notBefore,
970 const CIMDateTime notAfter,
971 const Uint32 depth,
972 const Uint32 errorCode,
973 const String errorString,
974 const Uint32 respCode)
975 {
976 _rep = new SSLCertificateInfoRep();
977 _rep->subjectName = subjectName;
978 _rep->issuerName = issuerName;
979 _rep->versionNumber = versionNumber;
980 _rep->serialNumber = serialNumber;
981 kumpf 1.16 _rep->notBefore = notBefore;
982 _rep->notAfter = notAfter;
983 _rep->depth = depth;
984 _rep->errorCode = errorCode;
985 _rep->errorString = errorString;
|
986 kumpf 1.14 _rep->respCode = respCode;
|
987 kumpf 1.9 }
988
989 SSLCertificateInfo::SSLCertificateInfo(
990 const SSLCertificateInfo& certificateInfo)
991 {
992 _rep = new SSLCertificateInfoRep();
993 _rep->subjectName = certificateInfo._rep->subjectName;
994 _rep->issuerName = certificateInfo._rep->issuerName;
|
995 kumpf 1.16 _rep->versionNumber = certificateInfo._rep->versionNumber;
996 _rep->serialNumber = certificateInfo._rep->serialNumber;
997 _rep->notBefore = certificateInfo._rep->notBefore;
998 _rep->notAfter = certificateInfo._rep->notAfter;
999 _rep->depth = certificateInfo._rep->depth;
|
1000 kumpf 1.9 _rep->errorCode = certificateInfo._rep->errorCode;
|
1001 kumpf 1.16 _rep->errorString = certificateInfo._rep->errorString;
|
1002 kumpf 1.9 _rep->respCode = certificateInfo._rep->respCode;
|
1003 kumpf 1.11 }
1004
1005 // Dummy constructor made private to disallow default construction
1006 SSLCertificateInfo::SSLCertificateInfo()
1007 {
|
1008 kumpf 1.1 }
1009
|
1010 kumpf 1.9 SSLCertificateInfo::~SSLCertificateInfo()
|
1011 kumpf 1.1 {
|
1012 kumpf 1.9 delete _rep;
|
1013 kumpf 1.1 }
1014
|
1015 kumpf 1.9 String SSLCertificateInfo::getSubjectName() const
|
1016 kumpf 1.1 {
|
1017 kumpf 1.9 return (_rep->subjectName);
|
1018 kumpf 1.1 }
1019
|
1020 kumpf 1.9 String SSLCertificateInfo::getIssuerName() const
|
1021 kumpf 1.1 {
|
1022 kumpf 1.9 return (_rep->issuerName);
|
1023 kumpf 1.1 }
1024
|
1025 kumpf 1.16 Uint32 SSLCertificateInfo::getVersionNumber() const
1026 {
1027 return (_rep->versionNumber);
1028 }
1029
1030 long SSLCertificateInfo::getSerialNumber() const
|
1031 kumpf 1.1 {
|
1032 kumpf 1.16 return (_rep->serialNumber);
|
1033 kumpf 1.1 }
1034
|
1035 kumpf 1.16 CIMDateTime SSLCertificateInfo::getNotBefore() const
1036 {
1037 return (_rep->notBefore);
1038 }
1039
1040 CIMDateTime SSLCertificateInfo::getNotAfter() const
1041 {
1042 return (_rep->notAfter);
1043 }
1044
1045 Uint32 SSLCertificateInfo::getErrorDepth() const
1046 {
1047 return (_rep->depth);
1048 }
1049
1050 Uint32 SSLCertificateInfo::getErrorCode() const
|
1051 kumpf 1.1 {
|
1052 kumpf 1.9 return (_rep->errorCode);
|
1053 kumpf 1.14 }
1054
|
1055 kumpf 1.16 void SSLCertificateInfo::setErrorCode(const int errorCode)
1056 {
1057 _rep->errorCode = errorCode;
1058 }
1059
1060 String SSLCertificateInfo::getErrorString() const
1061 {
1062 return (_rep->errorString);
1063 }
1064
1065 Uint32 SSLCertificateInfo::getResponseCode() const
|
1066 kumpf 1.14 {
1067 return (_rep->respCode);
|
1068 kumpf 1.1 }
1069
|
1070 kumpf 1.9 void SSLCertificateInfo::setResponseCode(const int respCode)
|
1071 kumpf 1.1 {
|
1072 kumpf 1.9 _rep->respCode = respCode;
|
1073 kumpf 1.1 }
1074
1075 PEGASUS_NAMESPACE_END
1076
|