(file) Return to SSLContext.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Common

  1 kumpf 1.1 //%/////////////////////////////////////////////////////////////////////////////
  2           //
  3 kumpf 1.2 // Copyright (c) 2000, 2001, 2002 BMC Software, Hewlett-Packard Company, IBM,
  4 kumpf 1.1 // The Open Group, Tivoli Systems
  5           //
  6           // Permission is hereby granted, free of charge, to any person obtaining a copy
  7 kumpf 1.2 // of this software and associated documentation files (the "Software"), to
  8           // deal in the Software without restriction, including without limitation the
  9           // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
 10 kumpf 1.1 // sell copies of the Software, and to permit persons to whom the Software is
 11           // furnished to do so, subject to the following conditions:
 12           // 
 13 kumpf 1.2 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
 14 kumpf 1.1 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
 15           // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
 16 kumpf 1.2 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
 17           // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 18           // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
 19 kumpf 1.1 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 20           // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 21           //
 22           //==============================================================================
 23           //
 24           // Author: Markus Mueller (sedgewick_de@yahoo.de)
 25           //
 26 kumpf 1.9 // Modified By: Nag Boranna, Hewlett-Packard Company (nagaraja_boranna@hp.com)
 27           //              Roger Kumpf, Hewlett-Packard Company (roger_kumpf@hp.com)
 28 kumpf 1.1 //
 29           //%/////////////////////////////////////////////////////////////////////////////
 30           
 31           #ifdef PEGASUS_HAS_SSL
 32           #include <openssl/err.h>
 33           #include <openssl/ssl.h>
 34           #include <openssl/rand.h>
 35           #else
 36           #define SSL_CTX void
 37           #endif // end of PEGASUS_HAS_SSL
 38           #include <Pegasus/Common/Destroyer.h>
 39           #include <Pegasus/Common/Socket.h>
 40           #include <Pegasus/Common/Tracer.h>
 41           
 42           #include "SSLContext.h"
 43           #include "SSLContextRep.h"
 44           
 45           PEGASUS_USING_STD;
 46           
 47           PEGASUS_NAMESPACE_BEGIN
 48           
 49 kumpf 1.4 // switch on if 'server needs certified client'
 50           //#define CLIENT_CERTIFY
 51 kumpf 1.1 
 52           //
 53           // use the following definitions only if SSL is available
 54           // 
 55 kumpf 1.3 #ifdef PEGASUS_HAS_SSL
 56 kumpf 1.1 
 57           //
 58           // certificate handling routine
 59           //
 60           
 61 kumpf 1.9 // ATTN-RK-20020905: This global variable is unsafe with multiple SSL contexts
 62           SSLCertificateVerifyFunction* verify_certificate;
 63 kumpf 1.1 
 64 kumpf 1.8 static int cert_verify(SSL_CTX *ctx, const char *cert_file, const char *key_file)
 65 kumpf 1.1 {
 66 kumpf 1.3     PEG_METHOD_ENTER(TRC_SSL, "cert_verify()");
 67 kumpf 1.1 
 68 kumpf 1.3     if (cert_file != NULL)
 69               {
 70                   if (SSL_CTX_use_certificate_file(ctx,cert_file,SSL_FILETYPE_PEM) <=0)
 71                   {
 72                       PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4, 
 73                           "---> SSL: no certificate found in " + String(cert_file));
 74                       PEG_METHOD_EXIT();
 75                       return 0;
 76                   }
 77                   if (key_file == NULL) key_file=cert_file;
 78                   if (SSL_CTX_use_PrivateKey_file(ctx,key_file,SSL_FILETYPE_PEM) <= 0)
 79                   {
 80                       PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4, 
 81                           "---> SSL: no private key found in " + String(key_file));
 82                       PEG_METHOD_EXIT();
 83                       return 0;
 84                   }
 85           
 86                   if (!SSL_CTX_check_private_key(ctx)) 
 87                   {
 88                       PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4, 
 89 kumpf 1.3                 "---> SSL: Private and public key do not match");
 90                       PEG_METHOD_EXIT();
 91                       return 0;
 92                   }
 93               }
 94               PEG_METHOD_EXIT();
 95               return -1;
 96 kumpf 1.1 }
 97           
 98           static int prepareForCallback(int preverifyOk, X509_STORE_CTX *ctx)
 99           {
100 kumpf 1.3     PEG_METHOD_ENTER(TRC_SSL, "prepareForCallback()");
101 kumpf 1.1 
102               char   buf[256];
103               X509   *err_cert;
104               int    err; 
105               int    depth;
106               String subjectName;
107               String issuerName;
108               int    verify_depth = 0;
109               int    verify_error = X509_V_OK;
110           
111               err_cert = X509_STORE_CTX_get_current_cert(ctx);
112               err = X509_STORE_CTX_get_error(ctx);
113           
114               depth = X509_STORE_CTX_get_error_depth(ctx);
115           
116               //FUTURE: Not sure what to do with these...?
117               //ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
118               //mydata = SSL_get_ex_data(ssl, mydata_index);
119           
120               X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);
121               subjectName = String(buf);
122 kumpf 1.1 
123               if (verify_depth >= depth)
124               {
125                   preverifyOk = 1;
126                   verify_error = X509_V_OK;
127               }
128               else
129               {
130                   preverifyOk = 0;
131                   verify_error = X509_V_ERR_CERT_CHAIN_TOO_LONG;
132                   X509_STORE_CTX_set_error(ctx, verify_error);
133               }
134           
135               if (!preverifyOk)
136               {
137 kumpf 1.3         PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4, 
138                       "---> SSL: verify error: " + String(X509_verify_cert_error_string(err)));
139 kumpf 1.1     }
140           
141               if (!preverifyOk && (err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT))
142               {
143                   X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256);
144                   issuerName = String(buf);
145               }
146               else
147               {
148                   X509_NAME_oneline(X509_get_issuer_name(err_cert), buf, 256);
149                   issuerName = String(buf);
150               }
151           
152               //
153               // Call the verify_certificate() callback
154               //
155 kumpf 1.9     SSLCertificateInfo certInfo(subjectName, issuerName, depth, err);
156 kumpf 1.1 
157               if (verify_certificate(certInfo))
158               {
159                   preverifyOk = 1;
160               }
161           
162               //delete certInfo;
163           
164               // ATTN-NB-03-05102002: Overriding the default verification result, may
165               // need to be changed to make it more generic.
166               if (preverifyOk)
167               {
168                   X509_STORE_CTX_set_error(ctx, verify_error);
169               }
170           
171               PEG_METHOD_EXIT();
172               return(preverifyOk);
173           }
174           
175           
176           //
177 kumpf 1.1 // SSL context area
178           //
179           // For the OSs that don't have /dev/random device file,
180           // must enable PEGASUS_SSL_RANDOMFILE flag.
181           //
182           SSLContextRep::SSLContextRep(const String& certPath,
183 kumpf 1.9                        SSLCertificateVerifyFunction* verifyCert,
184 kumpf 1.13                        const String& randomFile)
185 kumpf 1.1  {
186 kumpf 1.3      PEG_METHOD_ENTER(TRC_SSL, "SSLContextRep::SSLContextRep()");
187 kumpf 1.1  
188 kumpf 1.7      _certPath = certPath.getCString();
189 kumpf 1.1  
190                verify_certificate = verifyCert;
191            
192                //
193                // load SSL library
194                //
195                SSL_load_error_strings();
196                SSL_library_init();
197            
198            #ifdef PEGASUS_SSL_RANDOMFILE
199                
200                //
201 kumpf 1.13     // Initialise OpenSSL 0.9.5 random number generator.
202                //
203                if ( randomFile == String::EMPTY )
204                {
205                    PEG_METHOD_EXIT();
206                    throw( SSLException("Random seed file required"));
207                }
208            
209                int ret = RAND_load_file(randomFile.getCString(), -1);
210                if ( ret < 0 )
211                {
212                    PEG_METHOD_EXIT();
213                    throw( SSLException("RAND_load_file - failed"));
214                }
215            
216                //
217                // Will do more seeding
218                //
219                long seedNumber;
220                srandom((unsigned int)time(NULL)); // Initialize
221                seedNumber = random();
222 kumpf 1.13     RAND_seed((unsigned char *) &seedNumber, sizeof(seedNumber));
223            
224                int  seedRet = RAND_status();
225                if ( seedRet == 0 )
226                {
227                    PEG_TRACE_STRING(TRC_SSL, Tracer::LEVEL4, 
228                        "Not enough data , RAND_status = " + seedRet );
229                    PEG_METHOD_EXIT();
230                    throw( SSLException("RAND_seed - Not enough seed data "));
231                }
232 kumpf 1.1  
233            #endif // end of PEGASUS_SSL_RANDOMFILE
234            
235 kumpf 1.9      _sslContext = _makeSSLContext();
236            
237                PEG_METHOD_EXIT();
238            }
239            
240            SSLContextRep::SSLContextRep(const SSLContextRep& sslContextRep)
241            {
242                PEG_METHOD_ENTER(TRC_SSL, "SSLContextRep::SSLContextRep()");
243            
244                _certPath = sslContextRep._certPath;
245                // ATTN: verify_certificate is set implicitly in global variable
246                _randomFile = sslContextRep._randomFile;
247                _sslContext = _makeSSLContext();
248            
249                PEG_METHOD_EXIT();
250            }
251 kumpf 1.11 
252 kumpf 1.9  //
253            // Destructor
254            //
255            
256            SSLContextRep::~SSLContextRep()
257            {
258                PEG_METHOD_ENTER(TRC_SSL, "SSLContextRep::~SSLContextRep()");
259            
260                SSL_CTX_free(_sslContext);
261            
262                PEG_METHOD_EXIT();
263            }
264            
265            SSL_CTX * SSLContextRep::_makeSSLContext()
266            {
267                PEG_METHOD_ENTER(TRC_SSL, "SSLContextRep::_makeSSLContext()");
268            
269                SSL_CTX * sslContext = 0;
270            
271 kumpf 1.1      //
272                // create SSL Context Area
273                //
274            
275 kumpf 1.9      if (!( sslContext = SSL_CTX_new(SSLv23_method()) ))
276 kumpf 1.3      {
277                    PEG_METHOD_EXIT();
278 kumpf 1.5          throw( SSLException("Could not get SSL CTX"));
279 kumpf 1.3      }
280            
281            #ifdef PEGASUS_OS_HPUX
282 kumpf 1.9      if (!(SSL_CTX_set_cipher_list(sslContext, SSL_TXT_EXP40)))
283 kumpf 1.5          throw( SSLException("Could not set the cipher list"));
284 kumpf 1.3  #endif
285 kumpf 1.1  
286                //
287                // set overall SSL Context flags
288                //
289            
290 kumpf 1.9      SSL_CTX_set_quiet_shutdown(sslContext, 1);
291                SSL_CTX_set_mode(sslContext, SSL_MODE_AUTO_RETRY);
292                SSL_CTX_set_options(sslContext,SSL_OP_ALL);
293 kumpf 1.1  
294 kumpf 1.4  #ifdef CLIENT_CERTIFY
295 kumpf 1.9      SSL_CTX_set_verify(sslContext, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, 
296 kumpf 1.4          prepareForCallback);
297            #else
298 kumpf 1.10     if (verify_certificate != NULL)
299 kumpf 1.1      {
300 kumpf 1.9          SSL_CTX_set_verify(sslContext, 
301 kumpf 1.4              SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, prepareForCallback);
302 kumpf 1.1      }
303 kumpf 1.4  #endif
304 kumpf 1.1  
305                //
306                // check certificate given to me
307                //
308            
309 kumpf 1.9      if (!cert_verify(sslContext, _certPath, _certPath))
310 kumpf 1.3      {
311                    PEG_METHOD_EXIT();
312 kumpf 1.5          throw( SSLException("Could not get certificate and/or private key"));
313 kumpf 1.3      }
314 kumpf 1.1  
315 kumpf 1.3      PEG_METHOD_EXIT();
316 kumpf 1.9      return sslContext;
317 kumpf 1.1  }
318            
319            SSL_CTX * SSLContextRep::getContext() const 
320            {
321 kumpf 1.9      return _sslContext;
322 kumpf 1.1  }
323            #else 
324            
325            //
326 kumpf 1.9  // these definitions are used if ssl is not available
327 kumpf 1.1  //
328            
329            SSLContextRep::SSLContextRep(const String& certPath,
330 kumpf 1.9                         SSLCertificateVerifyFunction* verifyCert,
331 kumpf 1.13                        const String& randomFile) {}
332 kumpf 1.1  
333 kumpf 1.9  SSLContextRep::SSLContextRep(const SSLContextRep& sslContextRep) {}
334            
335 kumpf 1.1  SSLContextRep::~SSLContextRep() {}
336            
337 kumpf 1.9  SSL_CTX * SSLContextRep::_makeSSLContext() { return 0; }
338            
339            SSL_CTX * SSLContextRep::getContext() const { return 0; }
340 kumpf 1.1  
341            #endif // end of PEGASUS_HAS_SSL
342            
343            ///////////////////////////////////////////////////////////////////////////////
344            //
345            // SSLContext
346            //
347            ///////////////////////////////////////////////////////////////////////////////
348            
349            
350            SSLContext::SSLContext(
351                const String& certPath,
352 kumpf 1.9      SSLCertificateVerifyFunction* verifyCert,
353 kumpf 1.13     const String& randomFile)
354            {
355                _rep = new SSLContextRep(certPath, verifyCert, randomFile);
356            }
357            
358            #ifndef PEGASUS_REMOVE_DEPRECATED
359            SSLContext::SSLContext(
360                const String& certPath,
361                SSLCertificateVerifyFunction* verifyCert,
362 kumpf 1.1      const String& randomFile,
363 kumpf 1.6      Boolean isCIMClient)
364 kumpf 1.1  {
365 kumpf 1.13     _rep = new SSLContextRep(certPath, verifyCert, randomFile);
366 kumpf 1.1  }
367 kumpf 1.13 #endif
368 kumpf 1.1  
369 kumpf 1.9  SSLContext::SSLContext(const SSLContext& sslContext)
370            {
371                _rep = new SSLContextRep(*sslContext._rep);
372 kumpf 1.12 }
373            
374            // Dummy constructor made private to disallow default construction
375            SSLContext::SSLContext()
376            {
377 kumpf 1.9  }
378            
379 kumpf 1.1  SSLContext::~SSLContext() 
380            {
381                delete _rep;
382            }
383            
384            
385            ///////////////////////////////////////////////////////////////////////////////
386            //
387 kumpf 1.9  // SSLCertificateInfo
388 kumpf 1.1  //
389            ///////////////////////////////////////////////////////////////////////////////
390            
391 kumpf 1.9  class SSLCertificateInfoRep
392            {
393            public:
394                String subjectName;
395                String issuerName;
396                int    errorDepth;
397                int    errorCode;
398                int    respCode;
399            };
400            
401            
402            SSLCertificateInfo::SSLCertificateInfo(
403 kumpf 1.1      const String subjectName,
404                const String issuerName,
405                const int errorDepth,
406                const int errorCode)
407            {
408 kumpf 1.9      _rep = new SSLCertificateInfoRep();
409                _rep->subjectName = subjectName;
410                _rep->issuerName = issuerName;
411                _rep->errorDepth = errorDepth;
412                _rep->errorCode = errorCode;
413                _rep->respCode = 0;
414            }
415            
416            SSLCertificateInfo::SSLCertificateInfo(
417                const SSLCertificateInfo& certificateInfo)
418            {
419                _rep = new SSLCertificateInfoRep();
420                _rep->subjectName = certificateInfo._rep->subjectName;
421                _rep->issuerName = certificateInfo._rep->issuerName;
422                _rep->errorDepth = certificateInfo._rep->errorDepth;
423                _rep->errorCode = certificateInfo._rep->errorCode;
424                _rep->respCode = certificateInfo._rep->respCode;
425 kumpf 1.11 }
426            
427            // Dummy constructor made private to disallow default construction
428            SSLCertificateInfo::SSLCertificateInfo()
429            {
430 kumpf 1.1  }
431            
432 kumpf 1.9  SSLCertificateInfo::~SSLCertificateInfo()
433 kumpf 1.1  {
434 kumpf 1.9      delete _rep;
435 kumpf 1.1  }
436            
437 kumpf 1.9  String SSLCertificateInfo::getSubjectName() const
438 kumpf 1.1  {
439 kumpf 1.9      return (_rep->subjectName);
440 kumpf 1.1  }
441            
442 kumpf 1.9  String SSLCertificateInfo::getIssuerName() const
443 kumpf 1.1  {
444 kumpf 1.9      return (_rep->issuerName);
445 kumpf 1.1  }
446            
447 kumpf 1.9  int SSLCertificateInfo::getErrorDepth() const
448 kumpf 1.1  {
449 kumpf 1.9      return (_rep->errorDepth);
450 kumpf 1.1  }
451            
452 kumpf 1.9  int SSLCertificateInfo::getErrorCode() const
453 kumpf 1.1  {
454 kumpf 1.9      return (_rep->errorCode);
455 kumpf 1.1  }
456            
457 kumpf 1.9  void SSLCertificateInfo::setResponseCode(const int respCode)
458 kumpf 1.1  {
459 kumpf 1.9      _rep->respCode = respCode;
460 kumpf 1.1  }
461            
462            PEGASUS_NAMESPACE_END
463            

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2