(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 mday  1.13.2.1 // Modified By:
 27                //         Nag Boranna, Hewlett-Packard Company ( nagaraja_boranna@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 mday  1.13.2.1 
 50                // debug flag
 51                #define SSLCONTEXT_DEBUG(X) // X
 52                
 53                // switch on 'server needs certified client'
 54 kumpf 1.4      //#define CLIENT_CERTIFY
 55 kumpf 1.1      
 56 mday  1.13.2.1 
 57                #ifdef PEGASUS_HAS_SSL
 58 kumpf 1.1      //
 59                // use the following definitions only if SSL is available
 60                // 
 61                
 62                //
 63                // certificate handling routine
 64                //
 65                
 66 mday  1.13.2.1 VERIFY_CERTIFICATE verify_certificate;
 67 kumpf 1.1      
 68 mday  1.13.2.1 static int cert_verify(SSL_CTX *ctx, char *cert_file, char *key_file)
 69 kumpf 1.1      {
 70                
 71 mday  1.13.2.1    if (cert_file != NULL)
 72                   {
 73                       if (SSL_CTX_use_certificate_file(ctx,cert_file,SSL_FILETYPE_PEM) <=0)
 74                       {
 75                           SSLCONTEXT_DEBUG(cerr << "no certificate found in " << cert_file << endl;)
 76                           return 0;
 77                       }
 78                       if (key_file == NULL) key_file=cert_file;
 79                       if (SSL_CTX_use_PrivateKey_file(ctx,key_file,SSL_FILETYPE_PEM) <= 0)
 80                       {
 81                           SSLCONTEXT_DEBUG(cerr << "no private key found in " << key_file << endl;)
 82                           return 0;
 83                       }
 84                
 85                       if (!SSL_CTX_check_private_key(ctx)) 
 86                       {
 87                           SSLCONTEXT_DEBUG(cerr << "Private and public key do not match\n";)
 88                           return 0;
 89                       }
 90                   }
 91                   return -1;
 92 kumpf 1.1      }
 93                
 94                static int prepareForCallback(int preverifyOk, X509_STORE_CTX *ctx)
 95                {
 96 mday  1.13.2.1     PEG_METHOD_ENTER(TRC_SSL, "CertificateManager::prepareForCallback()");
 97 kumpf 1.1      
 98                    char   buf[256];
 99                    X509   *err_cert;
100                    int    err; 
101                    int    depth;
102                    String subjectName;
103                    String issuerName;
104                    int    verify_depth = 0;
105                    int    verify_error = X509_V_OK;
106                
107                    err_cert = X509_STORE_CTX_get_current_cert(ctx);
108                    err = X509_STORE_CTX_get_error(ctx);
109                
110                    depth = X509_STORE_CTX_get_error_depth(ctx);
111                
112                    //FUTURE: Not sure what to do with these...?
113                    //ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
114                    //mydata = SSL_get_ex_data(ssl, mydata_index);
115                
116                    X509_NAME_oneline(X509_get_subject_name(err_cert), buf, 256);
117                    subjectName = String(buf);
118 kumpf 1.1      
119                    if (verify_depth >= depth)
120                    {
121                        preverifyOk = 1;
122                        verify_error = X509_V_OK;
123                    }
124                    else
125                    {
126                        preverifyOk = 0;
127                        verify_error = X509_V_ERR_CERT_CHAIN_TOO_LONG;
128                        X509_STORE_CTX_set_error(ctx, verify_error);
129                    }
130                
131                    if (!preverifyOk)
132                    {
133 mday  1.13.2.1         SSLCONTEXT_DEBUG(cerr << "---> verify error: num = " << err << ", " 
134                            << X509_verify_cert_error_string(err) << ", " << depth 
135                            << ", " << buf <<  endl;)
136 kumpf 1.1          }
137                
138                    if (!preverifyOk && (err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT))
139                    {
140                        X509_NAME_oneline(X509_get_issuer_name(ctx->current_cert), buf, 256);
141                        issuerName = String(buf);
142                    }
143                    else
144                    {
145                        X509_NAME_oneline(X509_get_issuer_name(err_cert), buf, 256);
146                        issuerName = String(buf);
147                    }
148                
149                    //
150                    // Call the verify_certificate() callback
151                    //
152 mday  1.13.2.1     CertificateInfo certInfo(subjectName, issuerName, depth, err);
153 kumpf 1.1      
154                    if (verify_certificate(certInfo))
155                    {
156                        preverifyOk = 1;
157                    }
158                
159                    //delete certInfo;
160                
161                    // ATTN-NB-03-05102002: Overriding the default verification result, may
162                    // need to be changed to make it more generic.
163                    if (preverifyOk)
164                    {
165                        X509_STORE_CTX_set_error(ctx, verify_error);
166                    }
167                
168 mday  1.13.2.1     SSLCONTEXT_DEBUG(cerr << "verify return: " << preverifyOk << endl;)
169                
170 kumpf 1.1          PEG_METHOD_EXIT();
171                    return(preverifyOk);
172                }
173                
174                
175                //
176                // SSL context area
177                //
178                // For the OSs that don't have /dev/random device file,
179                // must enable PEGASUS_SSL_RANDOMFILE flag.
180                //
181 mday  1.13.2.1 // CIM clients must specify a SSL random file and also
182                // set isCIMClient to true. However, CIMserver does not
183                // seem to care the Random seed and /dev/random. 
184                //
185                //
186 kumpf 1.1      SSLContextRep::SSLContextRep(const String& certPath,
187 mday  1.13.2.1                        VERIFY_CERTIFICATE verifyCert,
188                                       const String& randomFile,
189                                       Boolean isCIMClient)
190                    throw(SSL_Exception)
191 kumpf 1.1      {
192 mday  1.13.2.1     SSLCONTEXT_DEBUG(cout << "Entering SSLContextRep::SSLContextRep()\n";)
193 kumpf 1.1      
194 mday  1.13.2.1     _certPath = certPath.allocateCString();
195 kumpf 1.1      
196                    verify_certificate = verifyCert;
197                
198                    //
199                    // load SSL library
200                    //
201                    SSL_load_error_strings();
202                    SSL_library_init();
203                
204                #ifdef PEGASUS_SSL_RANDOMFILE
205                    
206                    //
207 mday  1.13.2.1     // We will only need SSL Random Seed for CIM Clients
208                    // 
209                    if (isCIMClient) 
210                    {
211                       long  seedNumber;
212                       //
213                       // Initialise OpenSSL 0.9.5 random number generator.
214                       //
215                       if ( randomFile != String::EMPTY )
216                       {
217                          ArrayDestroyer<char> pRandomFile(randomFile.allocateCString());
218                          char* randFilename = pRandomFile.getPointer();
219                   
220                          SSLCONTEXT_DEBUG( cout << "load Rand file: name=" << randFilename << endl; )
221                          int ret = RAND_load_file(randFilename, -1);
222                          if ( ret < 0 )
223                          {
224                            SSLCONTEXT_DEBUG( cerr << " RAND_load_file failed, Status="<< ret << endl;)
225                            throw( SSL_Exception("RAND_load_file - failed"));
226                          }
227                          else
228 mday  1.13.2.1           {
229                            SSLCONTEXT_DEBUG( cerr << " RAND_load_file Status="<< ret << endl;)
230                          }
231                
232                          //
233                          // Will do more seeding
234                          //
235                          srandom((unsigned int)time(NULL)); // Initialize
236                          seedNumber = random();
237                          RAND_seed((unsigned char *) &seedNumber, sizeof(seedNumber));
238                
239                          int  seedRet = RAND_status();
240                          if ( seedRet == 0 )
241                          {
242                            SSLCONTEXT_DEBUG( cerr << " Not enough data , Rand Status="<< seedRet << endl;)
243                            throw( SSL_Exception("RAND_seed - Not enough seed data "));
244                          }
245                       }
246                       else
247                       {
248                           throw( SSL_Exception("Random seed file required"));
249 mday  1.13.2.1        }
250                 
251                     }
252 kumpf 1.1      
253                #endif // end of PEGASUS_SSL_RANDOMFILE
254                
255                    //
256                    // create SSL Context Area
257                    //
258                
259 mday  1.13.2.1     if (!( _SSLContext = SSL_CTX_new(SSLv23_method()) ))
260                        throw( SSL_Exception("Could not get SSL CTX"));
261 kumpf 1.1      
262                    //
263                    // set overall SSL Context flags
264                    //
265                
266 mday  1.13.2.1     SSL_CTX_set_quiet_shutdown(_SSLContext, 1);
267                    SSL_CTX_set_mode(_SSLContext, SSL_MODE_AUTO_RETRY);
268                    SSL_CTX_set_options(_SSLContext,SSL_OP_ALL);
269 kumpf 1.1      
270 kumpf 1.4      #ifdef CLIENT_CERTIFY
271 mday  1.13.2.1    SSL_CTX_set_verify(_SSLContext, SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, 
272                       prepareForCallback);
273                #else   
274                    if (verifyCert != NULL)
275 kumpf 1.1          {
276 mday  1.13.2.1         SSL_CTX_set_verify(_SSLContext, 
277 kumpf 1.4                  SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE, prepareForCallback);
278 kumpf 1.1          }
279 mday  1.13.2.1 #endif // end of  CLIENT_CERTIFY
280 kumpf 1.1      
281                    //
282                    // check certificate given to me
283                    //
284                
285 mday  1.13.2.1     if (!cert_verify(_SSLContext, _certPath, _certPath))
286                        throw( SSL_Exception("Could not get certificate and/or private key"));
287 kumpf 1.1      
288 mday  1.13.2.1     SSLCONTEXT_DEBUG(cout << "Leaving SSLContextRep::SSLContextRep()\n";)
289                }
290                
291                  
292                //
293                // Destructor
294                //
295                
296                SSLContextRep::~SSLContextRep()
297                {
298                    SSLCONTEXT_DEBUG(cout << "Entering SSLContextRep::~SSLContextRep()\n";)
299                
300                    free(_certPath);
301                    SSL_CTX_free(_SSLContext);
302                
303                    SSLCONTEXT_DEBUG(cout << "Leaving SSLContextRep::~SSLContextRep()\n";)
304 kumpf 1.1      }
305                
306                SSL_CTX * SSLContextRep::getContext() const 
307                {
308 mday  1.13.2.1     return _SSLContext;
309 kumpf 1.1      }
310                #else 
311                
312                //
313 mday  1.13.2.1 // these definitions are used if ssl is not availabel
314 kumpf 1.1      //
315                
316                SSLContextRep::SSLContextRep(const String& certPath,
317 mday  1.13.2.1                        VERIFY_CERTIFICATE verifyCert,
318                                       const String& randomFile,
319                                       Boolean isCIMClient) throw(SSL_Exception) {}
320 kumpf 1.9      
321 kumpf 1.1      SSLContextRep::~SSLContextRep() {}
322                
323 mday  1.13.2.1 SSL_CTX * SSLContextRep::getContext() const { return NULL; }
324 kumpf 1.1      
325                #endif // end of PEGASUS_HAS_SSL
326                
327                ///////////////////////////////////////////////////////////////////////////////
328                //
329                // SSLContext
330                //
331                ///////////////////////////////////////////////////////////////////////////////
332                
333                
334                SSLContext::SSLContext(
335                    const String& certPath,
336 mday  1.13.2.1     VERIFY_CERTIFICATE verifyCert,
337 kumpf 1.1          const String& randomFile,
338 mday  1.13.2.1     Boolean isCIMClient) throw(SSL_Exception) 
339 kumpf 1.12     {
340 mday  1.13.2.1     _rep = new SSLContextRep(certPath, verifyCert, randomFile, isCIMClient);
341 kumpf 1.9      }
342                
343 kumpf 1.1      SSLContext::~SSLContext() 
344                {
345                    delete _rep;
346                }
347                
348                
349                ///////////////////////////////////////////////////////////////////////////////
350                //
351 mday  1.13.2.1 // CertificateInfo
352 kumpf 1.1      //
353                ///////////////////////////////////////////////////////////////////////////////
354                
355 mday  1.13.2.1 CertificateInfo::CertificateInfo(
356 kumpf 1.1          const String subjectName,
357                    const String issuerName,
358                    const int errorDepth,
359                    const int errorCode)
360 mday  1.13.2.1     :
361                    _subjectName(subjectName),
362                    _issuerName(issuerName),
363                    _errorDepth(errorDepth),
364                    _errorCode(errorCode)
365 kumpf 1.1      {
366 mday  1.13.2.1     _respCode = 0;
367 kumpf 1.9      }
368                
369 mday  1.13.2.1 CertificateInfo::~CertificateInfo()
370 kumpf 1.9      {
371 kumpf 1.11     
372 kumpf 1.1      }
373                
374 mday  1.13.2.1 String CertificateInfo::getSubjectName() const
375 kumpf 1.1      {
376 mday  1.13.2.1     return (_subjectName);
377 kumpf 1.1      }
378                
379 mday  1.13.2.1 String CertificateInfo::getIssuerName() const
380 kumpf 1.1      {
381 mday  1.13.2.1     return (_issuerName);
382 kumpf 1.1      }
383                
384 mday  1.13.2.1 int CertificateInfo::getErrorDepth() const
385 kumpf 1.1      {
386 mday  1.13.2.1     return (_errorDepth);
387 kumpf 1.1      }
388                
389 mday  1.13.2.1 int CertificateInfo::getErrorCode() const
390 kumpf 1.1      {
391 mday  1.13.2.1     return (_errorCode);
392 kumpf 1.1      }
393                
394 mday  1.13.2.1 void CertificateInfo::setResponseCode(const int respCode)
395 kumpf 1.1      {
396 mday  1.13.2.1     _respCode = respCode;
397 kumpf 1.1      }
398                
399                PEGASUS_NAMESPACE_END
400                

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2