/[resiprocate]/main/sip/resiprocate/Security.cxx
ViewVC logotype

Contents of /main/sip/resiprocate/Security.cxx

Parent Directory Parent Directory | Revision Log Revision Log


Revision 5214 - (show annotations) (download)
Tue Aug 9 18:16:29 2005 UTC (14 years, 5 months ago) by daniel
File size: 64124 byte(s)
bug fixes.
1 #if defined(HAVE_CONFIG_H)
2 #include "resiprocate/config.hxx"
3 #endif
4
5 #include <ostream>
6 #include <fstream>
7
8 #include "resiprocate/Contents.hxx"
9 #include "resiprocate/MultipartSignedContents.hxx"
10 #include "resiprocate/Pkcs7Contents.hxx"
11 #include "resiprocate/PlainContents.hxx"
12 #include "resiprocate/Security.hxx"
13 #include "resiprocate/SecurityAttributes.hxx"
14 #include "resiprocate/Transport.hxx"
15 #include "resiprocate/SipMessage.hxx"
16 #include "resiprocate/os/BaseException.hxx"
17 #include "resiprocate/os/DataStream.hxx"
18 #include "resiprocate/os/Logger.hxx"
19 #include "resiprocate/os/Random.hxx"
20 #include "resiprocate/os/SHA1Stream.hxx"
21 #include "resiprocate/os/Socket.hxx"
22 #include "resiprocate/os/Timer.hxx"
23 #include "resiprocate/os/ParseBuffer.hxx"
24 #include "resiprocate/os/FileSystem.hxx"
25 #include "resiprocate/os/WinLeakCheck.hxx"
26
27
28 #if defined(USE_SSL)
29
30 #if !defined(WIN32)
31 #include <sys/types.h>
32 #include <sys/uio.h>
33 #include <sys/fcntl.h>
34 #include <unistd.h>
35 #include <dirent.h>
36 #endif
37
38 #include <sys/types.h>
39 #include <openssl/e_os2.h>
40 #include <openssl/evp.h>
41 #include <openssl/crypto.h>
42 #include <openssl/err.h>
43 #include <openssl/pem.h>
44 #include <openssl/pkcs7.h>
45 #include <openssl/ossl_typ.h>
46 #include <openssl/x509.h>
47 #include <openssl/x509v3.h>
48 #include <openssl/ssl.h>
49
50 using namespace resip;
51 using namespace std;
52
53 #define RESIPROCATE_SUBSYSTEM Subsystem::SIP
54
55 static const Data PEM(".pem");
56
57 static const Data
58 pemTypePrefixes( Security::PEMType pType )
59 {
60 static const Data rootCert("root_cert_");
61 static const Data domainCert("domain_cert_");
62 static const Data domainKey("domain_key_");
63 static const Data userCert("user_cert_");
64 static const Data userKey("user_key_");
65 static const Data unkonwKey("user_key_");
66
67 switch (pType)
68 {
69 case Security::RootCert: return rootCert;
70 case Security::DomainCert: return domainCert;
71 case Security::DomainPrivateKey: return domainKey;
72 case Security::UserCert: return userCert;
73 case Security::UserPrivateKey: return userKey;
74 default:
75 {
76 ErrLog( << "Some unkonw pem type prefix requested" << (int)(pType) );
77 assert(0);
78 }
79 }
80 return unkonwKey;
81 }
82
83
84 static Data
85 readIntoData(const Data& filename)
86 {
87 DebugLog( << "Trying to read file " << filename );
88
89 ifstream is;
90 is.open(filename.c_str(), ios::binary );
91 if ( !is.is_open() )
92 {
93 ErrLog( << "Could not open file " << filename << " for read");
94 throw BaseSecurity::Exception("Could not read file ",
95 __FILE__,__LINE__);
96 }
97
98 assert(is.is_open());
99
100 // get length of file:
101 is.seekg (0, ios::end);
102 int length = is.tellg();
103 is.seekg (0, ios::beg);
104
105 char* buffer = new char [length];
106
107 // read data as a block:
108 is.read (buffer,length);
109
110 Data target(Data::Take, buffer, length);
111
112 is.close();
113
114 return target;
115 }
116
117
118 static Data
119 getAor(const Data& filename, const Security::PEMType &pemType )
120 {
121 const Data& prefix = pemTypePrefixes( pemType );
122 return filename.substr(prefix.size(), filename.size() - prefix.size() - PEM.size());
123 }
124
125 static int
126 verifyCallback(int iInCode, X509_STORE_CTX *pInStore)
127 {
128 char cBuf1[500];
129 char cBuf2[500];
130 X509 *pErrCert;
131 int iErr = 0;
132 int iDepth = 0;
133 pErrCert = X509_STORE_CTX_get_current_cert(pInStore);
134 iErr = X509_STORE_CTX_get_error(pInStore);
135 iDepth = X509_STORE_CTX_get_error_depth(pInStore);
136
137 if (NULL != pErrCert)
138 X509_NAME_oneline(X509_get_subject_name(pErrCert),cBuf1,256);
139
140 sprintf(cBuf2,"depth=%d %s\n",iDepth,cBuf1);
141 if(!iInCode)
142 {
143 memset(cBuf2, 0, sizeof(cBuf2) );
144 sprintf(cBuf2, "\n Error %s", X509_verify_cert_error_string(pInStore->error) );
145 }
146
147 return iInCode;
148 }
149
150 Security::Security()
151 {
152 #ifdef WIN32
153 mPath = "C:\\sipCerts\\";
154 #else
155 mPath = getenv("HOME");
156 mPath += "/.sipCerts/";
157 #endif
158 }
159
160 Security::Security(const Data& directory) : mPath(directory)
161 {
162 // since the preloader won't work otherwise and VERY difficult to figure
163 // out.
164 if ( !mPath.postfix(Symbols::SLASH))
165 {
166 mPath += Symbols::SLASH;
167 }
168 }
169
170
171 void
172 Security::preload()
173 {
174 #if 1
175 FileSystem::Directory dir(mPath);
176 FileSystem::Directory::iterator it(dir);
177 for (; it != dir.end(); ++it)
178 {
179 Data name = *it;
180
181 if (name.postfix(PEM))
182 {
183 Data fileName = mPath + name;
184
185 DebugLog(<< "Trying to load file " << name );
186 try
187 {
188 if (name.prefix(pemTypePrefixes(UserCert)))
189 {
190 addCertPEM( UserCert, getAor(name, UserCert), readIntoData(fileName), false );
191 }
192 else if (name.prefix(pemTypePrefixes(UserPrivateKey)))
193 {
194 addPrivateKeyPEM( UserPrivateKey, getAor(name, UserPrivateKey), readIntoData(fileName), false);
195 }
196 else if (name.prefix(pemTypePrefixes(DomainCert)))
197 {
198 addCertPEM( DomainCert, getAor(name, DomainCert), readIntoData(fileName), false);
199 }
200 else if (name.prefix(pemTypePrefixes(DomainPrivateKey)))
201 {
202 addPrivateKeyPEM( DomainPrivateKey, getAor(name, DomainPrivateKey), readIntoData(fileName), false);
203 }
204 else if (name.prefix(pemTypePrefixes(RootCert)))
205 {
206 addRootCertPEM(readIntoData(fileName));
207 }
208 }
209 catch (...)
210 {
211 ErrLog(<< "Some problem reading " << fileName );
212 }
213
214 InfoLog(<<"Sucessfully loaded " << fileName );
215 }
216 }
217 #else
218 // CJ - TODO - delete this old crap
219 DIR* dir = opendir( mPath.c_str() );
220
221 if (!dir )
222 {
223 ErrLog( << "Error reading public key directory " << mPath );
224 return;
225 }
226
227 struct dirent * d = 0;
228 while (1)
229 {
230 d = readdir(dir);
231 if ( !d )
232 {
233 break;
234 }
235
236 Data name( d->d_name );
237 Data fileName = mPath+name;
238
239 if (name.postfix(PEM))
240 {
241 InfoLog( << "Going to try to read file " << fileName );
242
243 try
244 {
245 if (name.prefix(pemTypePrefixes(UserCert)))
246 {
247 addCertPEM( UserCert, getAor(name, UserCert), readIntoData(fileName), false );
248 }
249 else if (name.prefix(pemTypePrefixes(UserPrivateKey)))
250 {
251 addPrivateKeyPEM( UserPrivateKey, getAor(name, UserPrivateKey), readIntoData(fileName), false);
252 }
253 else if (name.prefix(pemTypePrefixes(DomainCert)))
254 {
255 addCertPEM( DomainCert, getAor(name, DomainCert), readIntoData(fileName), false);
256 }
257 else if (name.prefix(pemTypePrefixes(DomainPrivateKey)))
258 {
259 addPrivateKeyPEM( DomainPrivateKey, getAor(name, DomainPrivateKey), readIntoData(fileName), false);
260 }
261 else if (name.prefix(pemTypePrefixes(RootCert)))
262 {
263 addRootCertPEM(readIntoData(fileName));
264 }
265 }
266 catch (...)
267 {
268 ErrLog(<< "Some problem reading " << fileName );
269 }
270
271 InfoLog(<<"Sucessfully loaded " << fileName );
272 }
273 }
274 closedir( dir );
275 #endif
276 }
277
278
279 void
280 Security::onReadPEM(const Data& name, PEMType type, Data& buffer) const
281 {
282 Data filename = mPath + pemTypePrefixes(type) + name + PEM;
283
284 InfoLog (<< "Reading PEM file " << filename << " into " << name);
285 // .dlb. extra copy
286 buffer = readIntoData(filename);
287 }
288
289
290 void
291 Security::onWritePEM(const Data& name, PEMType type, const Data& buffer) const
292 {
293 Data filename = mPath + pemTypePrefixes(type) + name + PEM;
294 InfoLog (<< "Writing PEM file " << filename << " for " << name);
295 ofstream str(filename.c_str(), ios::binary);
296 if (!str)
297 {
298 ErrLog (<< "Can't write to " << filename);
299 throw BaseSecurity::Exception("Failed opening PEM file", __FILE__,__LINE__);
300 }
301 else
302 {
303 str.write(buffer.data(), buffer.size());
304 if (!str)
305 {
306 ErrLog (<< "Failed writing to " << filename << " " << buffer.size() << " bytes");
307 throw BaseSecurity::Exception("Failed writing PEM file", __FILE__,__LINE__);
308 }
309 }
310 }
311
312
313 void
314 Security::onRemovePEM(const Data& name, PEMType type) const
315 {
316 assert(0);
317 // TODO - should delete file
318 }
319
320
321 void
322 BaseSecurity::addCertDER (PEMType type,
323 const Data& key,
324 const Data& certDER,
325 bool write) const
326 {
327 assert( !certDER.empty() );
328
329 X509* cert = 0;
330
331 #if (OPENSSL_VERSION_NUMBER < 0x0090800fL )
332 unsigned char* in = (unsigned char*)certDER.data();
333 #else
334 unsigned const char* in = (unsigned const char*)certDER.data();
335 #endif
336
337 if (d2i_X509(&cert,&in,certDER.size()) == 0)
338 {
339 ErrLog(<< "Could not read DER certificate from " << certDER );
340 throw BaseSecurity::Exception("Could not read DER certificate ",
341 __FILE__,__LINE__);
342 }
343 addCertX509(type,key,cert,write);
344 }
345
346
347 void
348 BaseSecurity::addCertPEM (PEMType type,
349 const Data& name,
350 const Data& certPEM,
351 bool write) const
352 {
353 assert( !certPEM.empty() );
354 X509* cert=NULL;
355
356 BIO* in = BIO_new_mem_buf(const_cast<char*>(certPEM.c_str()), -1);
357 if ( !in )
358 {
359 ErrLog(<< "Could not create BIO buffer from '" << certPEM << "'");
360 throw Exception("Could not create BIO buffer", __FILE__,__LINE__);
361 }
362 try
363 {
364 BIO_set_close(in, BIO_NOCLOSE);
365 cert = PEM_read_bio_X509(in,0,0,0);
366 }
367 catch(...)
368 {
369 BIO_free(in);
370 throw;
371 }
372
373 addCertX509(type,name,cert,write);
374
375 BIO_free(in);
376 }
377
378
379 void
380 BaseSecurity::addCertX509(PEMType type, const Data& key, X509* cert, bool write) const
381 {
382 switch (type)
383 {
384 case DomainCert:
385 {
386 mDomainCerts.insert(std::make_pair(key, cert));
387 }
388 break;
389 case UserCert:
390 {
391 mUserCerts.insert(std::make_pair(key, cert));
392 }
393 break;
394 case RootCert:
395 {
396 X509_STORE_add_cert(mRootCerts,cert);
397 }
398 break;
399 default:
400 {
401 assert(0);
402 }
403 }
404
405 if (write)
406 {
407 // creates a read/write BIO buffer.
408 BIO *out = BIO_new(BIO_s_mem());
409 assert(out);
410 try
411 {
412 int ret = PEM_write_bio_X509(out, cert);
413 assert(ret);
414
415 BIO_flush(out);
416 // get content in BIO buffer to our buffer.
417 char* p = 0;
418 size_t len = BIO_get_mem_data(out,&p);
419 assert(p);
420 assert(len);
421 Data buf(Data::Borrow, p, len);
422
423 this->onWritePEM(key, type, buf);
424 }
425 catch(...)
426 {
427 BIO_free(out);
428 throw;
429 }
430 BIO_free(out);
431 }
432 }
433
434
435 bool
436 BaseSecurity::hasCert (PEMType type, const Data& aor) const
437 {
438 assert( !aor.empty() );
439 X509Map& certs = (type == DomainCert ? mDomainCerts : mUserCerts);
440
441 X509Map::iterator where = certs.find(aor);
442 if (where != certs.end())
443 {
444 return true;
445 }
446
447 try
448 {
449 Data certPEM;
450 onReadPEM(aor, type, certPEM);
451 if (certPEM.empty())
452 {
453 return false;
454 }
455 BaseSecurity* mutable_this = const_cast<BaseSecurity*>(this);
456 mutable_this->addCertPEM(type, aor, certPEM, false);
457 }
458 catch (...)
459 {
460 return false;
461 }
462
463 assert( certs.find(aor) != certs.end() );
464
465 return true;
466 }
467
468
469 void
470 BaseSecurity::removeCert (PEMType type, const Data& aor)
471 {
472 assert( !aor.empty() );
473 X509Map& certs = (type == DomainCert ? mDomainCerts : mUserCerts);
474
475 X509Map::iterator iter = certs.find(aor);
476 if (iter != certs.end())
477 {
478 X509_free(iter->second);
479 certs.erase(iter);
480
481 onRemovePEM(aor, type);
482 }
483
484 assert( certs.find(aor) == certs.end() );
485 }
486
487
488 Data
489 BaseSecurity::getCertDER (PEMType type, const Data& key) const
490 {
491 assert( !key.empty() );
492
493 if (hasCert(type, key) == false)
494 {
495 ErrLog(<< "Could find certificate for '" << key << "'");
496 throw BaseSecurity::Exception("Could not find certificate", __FILE__,__LINE__);
497 }
498
499 X509Map& certs = (type == DomainCert ? mDomainCerts : mUserCerts);
500 BaseSecurity::X509Map::iterator where = certs.find(key);
501 if (where == certs.end())
502 {
503 // not supposed to happen,
504 // hasCert() should have inserted a value into certs
505 // or we should have throwed.
506 assert(0);
507 }
508
509 //assert(0); // the code following this has no hope of working
510
511 X509* x = where->second;
512 unsigned char* buffer=0;
513 int len = i2d_X509(x, &buffer);
514
515 // !kh!
516 // Although len == 0 is not an error, I am not sure what quite to do.
517 // Asserting for now.
518 assert(len != 0);
519 if(len < 0)
520 {
521 ErrLog(<< "Could encode certificate of '" << key << "' to DER form");
522 throw BaseSecurity::Exception("Could encode certificate to DER form", __FILE__,__LINE__);
523 }
524 return Data(Data::Take, (char*)buffer, len);
525 }
526
527
528 void
529 BaseSecurity::addPrivateKeyPKEY(PEMType type,
530 const Data& name,
531 EVP_PKEY* pKey,
532 bool write) const
533 {
534 PrivateKeyMap& privateKeys = (type == DomainPrivateKey ?
535 mDomainPrivateKeys : mUserPrivateKeys);
536
537 // make a copy of the the key
538 assert( EVP_PKEY_type(pKey->type) == EVP_PKEY_RSA );
539 RSA* rsa = EVP_PKEY_get1_RSA(pKey);
540 assert( rsa );
541 EVP_PKEY* nKey = EVP_PKEY_new();
542 assert( nKey );
543 EVP_PKEY_set1_RSA(nKey, rsa);
544
545 privateKeys.insert(std::make_pair(name, nKey));
546
547 if (write)
548 {
549 // figure out a passPhrase to encrypt with
550 char* kstr=NULL;
551 int klen=0;
552 if (type != DomainPrivateKey)
553 {
554 PassPhraseMap::const_iterator iter = mUserPassPhrases.find(name);
555 if(iter != mUserPassPhrases.end())
556 {
557 Data passPhrase = iter->second;
558
559 kstr = (char*)passPhrase.c_str(); // TODO !cj! mem leak
560 klen = passPhrase.size();
561 }
562 }
563
564 BIO *bio = BIO_new(BIO_s_mem());
565 assert(bio);
566 try
567 {
568 assert( EVP_des_ede3_cbc() );
569 const EVP_CIPHER* cipher = EVP_des_ede3_cbc();
570 if (kstr == NULL )
571 {
572 cipher = NULL;
573 }
574 #if 0 // TODO - need to figure out what format to write in
575 int ret = PEM_write_bio_PrivateKey(bio, pKey, cipher,
576 (unsigned char*)kstr, klen,
577 NULL, NULL);
578 #else
579 int ret = PEM_write_bio_PKCS8PrivateKey(bio, pKey, cipher,
580 kstr, klen,
581 NULL, NULL);
582 #endif
583 assert(ret);
584
585 BIO_flush(bio);
586 char* p = 0;
587 size_t len = BIO_get_mem_data(bio,&p);
588 assert(p);
589 assert(len);
590 Data pem(Data::Borrow, p, len);
591 onWritePEM(name, type, pem );
592 }
593 catch(...)
594 {
595 BIO_free(bio);
596 throw;
597 }
598 BIO_free(bio);
599 }
600 }
601
602
603 void
604 BaseSecurity::addPrivateKeyDER( PEMType type,
605 const Data& name,
606 const Data& privateKeyDER,
607 bool write ) const
608 {
609 assert( !name.empty() );
610 assert( !privateKeyDER.empty() );
611
612 char* passPhrase = 0;
613 if (type != DomainPrivateKey)
614 {
615 PassPhraseMap::const_iterator iter = mUserPassPhrases.find(name);
616 if(iter != mUserPassPhrases.end())
617 {
618 passPhrase = const_cast<char*>(iter->second.c_str());
619 }
620 }
621
622 BIO* in = BIO_new_mem_buf(const_cast<char*>(privateKeyDER.c_str()), -1);
623 if ( !in )
624 {
625 ErrLog(<< "Could create BIO buffer from '" << privateKeyDER << "'");
626 throw Exception("Could not create BIO buffer", __FILE__,__LINE__);
627 }
628
629 try
630 {
631 BIO_set_close(in, BIO_NOCLOSE);
632
633 EVP_PKEY* privateKey;
634 if (d2i_PKCS8PrivateKey_bio(in, &privateKey, 0, passPhrase) == 0)
635 {
636 ErrLog(<< "Could not read private key from <" << privateKeyDER << ">" );
637 throw Exception("Could not read private key ", __FILE__,__LINE__);
638 }
639
640 addPrivateKeyPKEY(type,name,privateKey,write);
641 }
642 catch(...)
643 {
644 if (passPhrase)
645 {
646 free( passPhrase ); passPhrase=NULL;
647 }
648 BIO_free(in);
649 throw;
650 }
651
652 if (passPhrase)
653 {
654 free( passPhrase ); passPhrase=NULL;
655 }
656 BIO_free(in);
657 }
658
659
660 void
661 BaseSecurity::addPrivateKeyPEM( PEMType type,
662 const Data& name,
663 const Data& privateKeyPEM,
664 bool write ) const
665 {
666 assert( !name.empty() );
667 assert( !privateKeyPEM.empty() );
668
669 BIO* in = BIO_new_mem_buf(const_cast<char*>(privateKeyPEM.c_str()), -1);
670 if ( !in )
671 {
672 ErrLog(<< "Could create BIO buffer from '" << privateKeyPEM << "'");
673 throw Exception("Could not create BIO buffer", __FILE__,__LINE__);
674 }
675
676 char* passPhrase = 0;
677 try
678 {
679 if (type == UserPrivateKey)
680 {
681 PassPhraseMap::const_iterator iter = mUserPassPhrases.find(name);
682 if(iter != mUserPassPhrases.end())
683 {
684 passPhrase = const_cast<char*>(iter->second.c_str());
685 }
686 }
687 BIO_set_close(in, BIO_NOCLOSE);
688
689 EVP_PKEY* privateKey=0;
690 if ( ( privateKey = PEM_read_bio_PrivateKey(in, NULL, 0, passPhrase)) == NULL)
691 {
692 ErrLog(<< "Could not read private key from <" << privateKeyPEM << ">" );
693 throw Exception("Could not read private key ", __FILE__,__LINE__);
694 }
695
696 addPrivateKeyPKEY(type,name,privateKey,write);
697 }
698 catch(...)
699 {
700 if (passPhrase)
701 {
702 free( passPhrase ); passPhrase=NULL;
703 }
704 BIO_free(in);
705 throw;
706 }
707
708 if (passPhrase)
709 {
710 free( passPhrase ); passPhrase=NULL;
711 }
712 BIO_free(in);
713 }
714
715
716 bool
717 BaseSecurity::hasPrivateKey( PEMType type,
718 const Data& key ) const
719 {
720 assert( !key.empty() );
721
722 PrivateKeyMap& privateKeys = (type == DomainPrivateKey
723 ? mDomainPrivateKeys : mUserPrivateKeys);
724
725 PrivateKeyMap::const_iterator where = privateKeys.find(key);
726 if (where != privateKeys.end())
727 {
728 return true;
729 }
730
731 Data privateKeyPEM;
732 try
733 {
734 onReadPEM(key, type, privateKeyPEM);
735 BaseSecurity* mutable_this = const_cast<BaseSecurity*>(this);
736 mutable_this->addPrivateKeyPEM(type, key, privateKeyPEM, false);
737 }
738 catch(...)
739 {
740 return false;
741 }
742
743 return true;
744 }
745
746
747 Data
748 BaseSecurity::getPrivateKeyPEM( PEMType type,
749 const Data& key) const
750 {
751 assert( !key.empty() );
752
753 if ( !hasPrivateKey(type, key) )
754 {
755 ErrLog(<< "Could find private key for '" << key << "'");
756 throw Exception("Could not find private key", __FILE__,__LINE__);
757 }
758
759 PrivateKeyMap& privateKeys = (type == DomainPrivateKey ? mDomainPrivateKeys : mUserPrivateKeys);
760
761 PrivateKeyMap::const_iterator where = privateKeys.find(key);
762 char* p = 0;
763 if (type != DomainPrivateKey)
764 {
765 PassPhraseMap::const_iterator iter = mUserPassPhrases.find(key);
766 if (iter != mUserPassPhrases.end())
767 {
768 p = const_cast<char*>(iter->second.c_str());
769 }
770 }
771
772 assert(0); // TODO - following code has no hope of working
773
774 // !kh!
775 // creates a read/write BIO buffer.
776 BIO *out = BIO_new(BIO_s_mem());
777 assert(out);
778 EVP_PKEY* pk = where->second;
779 assert(pk);
780
781 // write pk to out using key phrase p, with no cipher.
782 int ret = PEM_write_bio_PrivateKey(out, pk, 0, 0, 0, 0, p); // paraters
783 // are in the wrong order
784 assert(ret == 1);
785
786 // get content in BIO buffer to our buffer.
787 // hand our buffer to a Data object.
788 BIO_flush(out);
789 char* buf = 0;
790 int len = BIO_get_mem_data(out, &buf);
791 Data retVal(Data::Borrow, buf, len);
792
793 BIO_free(out);
794
795 return retVal;
796 }
797
798
799 Data
800 BaseSecurity::getPrivateKeyDER( PEMType type,
801 const Data& key) const
802 {
803 assert( !key.empty() );
804
805 if ( !hasPrivateKey(type, key) )
806 {
807 ErrLog(<< "Could find private key for '" << key << "'");
808 throw Exception("Could not find private key", __FILE__,__LINE__);
809 }
810
811 PrivateKeyMap& privateKeys = (type == DomainPrivateKey ? mDomainPrivateKeys : mUserPrivateKeys);
812
813 PrivateKeyMap::const_iterator where = privateKeys.find(key);
814 char* p = 0;
815 if (type != DomainPrivateKey)
816 {
817 PassPhraseMap::const_iterator iter = mUserPassPhrases.find(key);
818 if(iter != mUserPassPhrases.end())
819 {
820 p = const_cast<char*>(iter->second.c_str());
821 }
822 }
823
824 assert(0); // TODO - following code has no hope of working
825
826 // !kh!
827 // creates a read/write BIO buffer.
828 BIO *out = BIO_new(BIO_s_mem());
829 assert(out);
830 EVP_PKEY* pk = where->second;
831 assert(pk);
832
833 // write pk to out using key phrase p, with no cipher.
834 int ret = i2d_PKCS8PrivateKey_bio(out, pk, 0, 0, 0, 0, p);
835 assert(ret == 1);
836
837 // get content in BIO buffer to our buffer.
838 // hand our buffer to a Data object.
839 BIO_flush(out);
840 char* buf = 0;
841 int len = BIO_get_mem_data(out, &buf);
842 Data retVal(Data::Borrow, buf, len);
843
844 BIO_free(out);
845
846 return retVal;
847 }
848
849
850 void
851 BaseSecurity::removePrivateKey(PEMType type, const Data& key)
852 {
853 assert( !key.empty() );
854
855 PrivateKeyMap& privateKeys = (type == DomainPrivateKey ? mDomainPrivateKeys : mUserPrivateKeys);
856
857 assert( !key.empty() );
858 PrivateKeyMap::iterator iter = privateKeys.find(key);
859 if (iter != privateKeys.end())
860 {
861 EVP_PKEY_free(iter->second);
862 privateKeys.erase(iter);
863
864 onRemovePEM(key, type);
865 }
866 }
867
868
869 Security::Exception::Exception(const Data& msg, const Data& file, const int line)
870 : BaseException(msg,file,line)
871 {
872 }
873
874
875 BaseSecurity::BaseSecurity () :
876 mTlsCtx(0),
877 mSslCtx(0),
878 mRootCerts(0)
879 {
880 int ret;
881
882 initialize();
883
884 mRootCerts = X509_STORE_new();
885 assert(mRootCerts);
886
887 // static char* cipher="RSA+SHA+AES+3DES";
888 // static char* cipher="TLS_RSA_WITH_AES_128_CBC_SHA:TLS_RSA_WITH_3DES_EDE_CBC_SHA";
889 //static char* cipher="ALL";
890 //static char* cipher="RSA+DSS+AES+3DES+DES+RC4+SHA1+MD5";
891 static char* cipher="!SSLv2:!ADH:RSA+AES:DSS+AES:RSA+3DES:DSS+3DES";
892 /*
893 use: openssl ciphers -v <string> to test cipher string
894 The resulting cipher suite using OpenSSL 0.97g is:
895 AES256-SHA SSLv3 Kx=RSA Au=RSA Enc=AES(256) Mac=SHA1
896 AES128-SHA SSLv3 Kx=RSA Au=RSA Enc=AES(128) Mac=SHA1
897 DHE-DSS-AES256-SHA SSLv3 Kx=DH Au=DSS Enc=AES(256) Mac=SHA1
898 DHE-DSS-AES128-SHA SSLv3 Kx=DH Au=DSS Enc=AES(128) Mac=SHA1
899 DES-CBC3-SHA SSLv3 Kx=RSA Au=RSA Enc=3DES(168) Mac=SHA1
900 EDH-DSS-DES-CBC3-SHA SSLv3 Kx=DH Au=DSS Enc=3DES(168) Mac=SHA1
901 */
902
903 mTlsCtx = SSL_CTX_new( TLSv1_method() );
904 assert(mTlsCtx);
905 SSL_CTX_set_cert_store(mTlsCtx, mRootCerts);
906 SSL_CTX_set_verify(mTlsCtx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE,
907 verifyCallback);
908 ret = SSL_CTX_set_cipher_list(mTlsCtx,cipher);
909 assert(ret);
910
911 mSslCtx = SSL_CTX_new( SSLv23_method() );
912 assert(mSslCtx);
913 SSL_CTX_set_cert_store(mSslCtx, mRootCerts);
914 SSL_CTX_set_verify(mSslCtx, SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE,
915 verifyCallback);
916 ret = SSL_CTX_set_cipher_list(mSslCtx,cipher);
917 assert(ret);
918 }
919
920
921 template<class T, class Func>
922 void clearMap(T& m, Func& clearFunc)
923 {
924 for (typename T::iterator it = m.begin(); it != m.end(); it++)
925 {
926 clearFunc(it->second);
927 }
928 m.clear();
929 }
930
931 BaseSecurity::~BaseSecurity ()
932 {
933 // cleanup certificates
934 clearMap(mDomainCerts, X509_free);
935 clearMap(mUserCerts, X509_free);
936
937 // cleanup private keys
938 clearMap(mDomainPrivateKeys, EVP_PKEY_free);
939 clearMap(mUserPrivateKeys, EVP_PKEY_free);
940
941 // cleanup root certs
942 X509_STORE_free(mRootCerts);
943 #if 0 // TODO - mem leak but seg faults
944 {
945 // cleanup SSL_CTXes
946 if (mTlsCtx)
947 {
948 SSL_CTX_free(mTlsCtx);mTlsCtx=0;
949 }
950 if (mSslCtx)
951 {
952 SSL_CTX_free(mSslCtx);mSslCtx=0;
953 }
954 }
955 #endif
956 }
957
958
959 void
960 BaseSecurity::initialize ()
961 {
962 // TODO !cj! - this should only be called once - ues pthread_once
963 // It is not a huge bug if this runs twice because the calls cause no harm
964 static bool done=false;
965 if (!done)
966 {
967 DebugLog( << "Setting up SSL library" );
968
969 SSL_library_init();
970 SSL_load_error_strings();
971 OpenSSL_add_all_algorithms();
972
973 Random::initialize();
974 Timer::getTimeMs(); // initalize time offsets
975
976 // make sure that necessary algorithms exist:
977 assert(EVP_des_ede3_cbc());
978
979 done = true;
980 }
981 }
982
983
984 Security::CertificateInfoContainer
985 BaseSecurity::getRootCertDescriptions() const
986 {
987 // !kh!
988 // need to be implemented.
989 assert(0); // TODO
990 return CertificateInfoContainer();
991 }
992
993
994 void
995 BaseSecurity::addRootCertPEM(const Data& x509PEMEncodedRootCerts)
996 {
997 assert( mRootCerts );
998 #if 1
999 addCertPEM(RootCert,Data::Empty,x509PEMEncodedRootCerts,false);
1000 #else
1001 assert( !x509PEMEncodedRootCerts.empty() );
1002
1003 static X509_LOOKUP_METHOD x509_pemstring_lookup =
1004 {
1005 "Load cert from PEM string into cache",
1006 NULL, /* new */
1007 NULL, /* free */
1008 NULL, /* init */
1009 NULL, /* shutdown */
1010 pemstring_ctrl,/* ctrl */
1011 NULL, /* get_by_subject */
1012 NULL, /* get_by_issuer_serial */
1013 NULL, /* get_by_fingerprint */
1014 NULL, /* get_by_alias */
1015 };
1016
1017 if (mRootCerts == 0)
1018 {
1019 mRootCerts = X509_STORE_new();
1020 }
1021
1022 assert( mRootCerts );
1023
1024 X509_LOOKUP* lookup = X509_STORE_add_lookup(mRootCerts, &x509_pemstring_lookup);
1025
1026 if (lookup == NULL)
1027 throw Exception("Error in BaseSecurity::addRootCertPEM()", __FILE__,__LINE__);
1028
1029 // !kh!
1030 // bug, no error handling here.
1031 X509_LOOKUP_ctrl(lookup, X509_L_FILE_LOAD, x509PEMEncodedRootCerts.c_str(), 0, 0);
1032 #endif
1033 }
1034
1035
1036 void
1037 BaseSecurity::addDomainCertPEM(const Data& domainName, const Data& certPEM)
1038 {
1039 addCertPEM(DomainCert, domainName, certPEM, true);
1040 }
1041
1042
1043 void
1044 BaseSecurity::addDomainCertDER(const Data& domainName, const Data& certDER)
1045 {
1046 addCertDER(DomainCert, domainName, certDER, true);
1047 }
1048
1049
1050 bool
1051 BaseSecurity::hasDomainCert(const Data& domainName) const
1052 {
1053 return hasCert(DomainCert, domainName);
1054 }
1055
1056
1057 void
1058 BaseSecurity::removeDomainCert(const Data& domainName)
1059 {
1060 return removeCert(DomainCert, domainName);
1061 }
1062
1063
1064 Data
1065 BaseSecurity::getDomainCertDER(const Data& domainName) const
1066 {
1067 return getCertDER(DomainCert, domainName);
1068 }
1069
1070
1071 void
1072 BaseSecurity::addDomainPrivateKeyPEM(const Data& domainName, const Data& privateKeyPEM)
1073 {
1074 addPrivateKeyPEM(DomainPrivateKey, domainName, privateKeyPEM, true);
1075 }
1076
1077
1078 bool
1079 BaseSecurity::hasDomainPrivateKey(const Data& domainName) const
1080 {
1081 return hasPrivateKey(DomainPrivateKey, domainName);
1082 }
1083
1084
1085 void
1086 BaseSecurity::removeDomainPrivateKey(const Data& domainName)
1087 {
1088 removePrivateKey(DomainPrivateKey, domainName);
1089 }
1090
1091
1092 Data
1093 BaseSecurity::getDomainPrivateKeyPEM(const Data& domainName) const
1094 {
1095 return getPrivateKeyPEM(DomainPrivateKey, domainName);
1096 }
1097
1098
1099 void
1100 BaseSecurity::addUserCertPEM(const Data& aor, const Data& certPEM)
1101 {
1102 addCertPEM(UserCert, aor, certPEM, true);
1103 }
1104
1105
1106 void
1107 BaseSecurity::addUserCertDER(const Data& aor, const Data& certDER)
1108 {
1109 addCertDER(UserCert, aor, certDER, true);
1110 }
1111
1112
1113 bool
1114 BaseSecurity::hasUserCert(const Data& aor) const
1115 {
1116 return hasCert(UserCert, aor);
1117 }
1118
1119
1120 void
1121 BaseSecurity::removeUserCert(const Data& aor)
1122 {
1123 removeCert(UserCert, aor);
1124 }
1125
1126
1127 Data
1128 BaseSecurity::getUserCertDER(const Data& aor) const
1129 {
1130 return getCertDER(UserCert, aor);
1131 }
1132
1133
1134 void
1135 BaseSecurity::setUserPassPhrase(const Data& aor, const Data& passPhrase)
1136 {
1137 assert(!aor.empty());
1138
1139 PassPhraseMap::iterator iter = mUserPassPhrases.find(aor);
1140 if (iter == mUserPassPhrases.end())
1141 {
1142 mUserPassPhrases.insert(std::make_pair(aor, passPhrase));
1143 }
1144 }
1145
1146
1147 bool
1148 BaseSecurity::hasUserPassPhrase(const Data& aor) const
1149 {
1150 assert(aor.empty());
1151
1152 PassPhraseMap::const_iterator iter = mUserPassPhrases.find(aor);
1153 if (iter == mUserPassPhrases.end())
1154 {
1155 return false;
1156 }
1157 else
1158 {
1159 return true;
1160 }
1161 }
1162
1163
1164 void
1165 BaseSecurity::removeUserPassPhrase(const Data& aor)
1166 {
1167 assert(aor.empty());
1168
1169 PassPhraseMap::iterator iter = mUserPassPhrases.find(aor);
1170 if(iter != mUserPassPhrases.end())
1171 {
1172 mUserPassPhrases.erase(iter);
1173 }
1174 }
1175
1176
1177 Data
1178 BaseSecurity::getUserPassPhrase(const Data& aor) const
1179 {
1180 assert(aor.empty());
1181
1182 PassPhraseMap::const_iterator iter = mUserPassPhrases.find(aor);
1183 if(iter == mUserPassPhrases.end())
1184 {
1185 return iter->second;
1186 }
1187 else
1188 {
1189 return Data::Empty;
1190 }
1191 }
1192
1193
1194 void
1195 BaseSecurity::addUserPrivateKeyPEM(const Data& aor, const Data& cert)
1196 {
1197 addPrivateKeyPEM(UserPrivateKey, aor, cert, true);
1198 }
1199
1200
1201 void
1202 BaseSecurity::addUserPrivateKeyDER(const Data& aor, const Data& cert)
1203 {
1204 addPrivateKeyDER(UserPrivateKey, aor, cert, true);
1205 }
1206
1207
1208 bool
1209 BaseSecurity::hasUserPrivateKey(const Data& aor) const
1210 {
1211 return hasPrivateKey(UserPrivateKey, aor);
1212 }
1213
1214
1215 void
1216 BaseSecurity::removeUserPrivateKey(const Data& aor)
1217 {
1218 removePrivateKey(UserPrivateKey, aor);
1219 }
1220
1221
1222 Data
1223 BaseSecurity::getUserPrivateKeyPEM(const Data& aor) const
1224 {
1225 return getPrivateKeyPEM(UserPrivateKey, aor);
1226 }
1227
1228
1229 Data
1230 BaseSecurity::getUserPrivateKeyDER(const Data& aor) const
1231 {
1232 return getPrivateKeyDER(UserPrivateKey, aor);
1233 }
1234
1235
1236 void
1237 BaseSecurity::generateUserCert (const Data& pAor, int expireDays, int keyLen )
1238 {
1239 int ret;
1240
1241 InfoLog( <<"Generating new user cert for " << pAor );
1242
1243 Data domain;
1244 Data aor;
1245
1246 try
1247 {
1248 Uri uri( Data("sip:")+pAor );
1249 aor = uri.getAor();
1250 domain = uri.host();
1251 }
1252 catch (...)
1253 {
1254 ErrLog( <<"Invalid aor passed to generateUserCert");
1255 throw Exception("Bad aor passed to generateUserCert", __FILE__,__LINE__);
1256 }
1257
1258 // Make sure that necessary algorithms exist:
1259 assert(EVP_sha1());
1260
1261 RSA* rsa = RSA_generate_key(keyLen, RSA_F4, NULL, NULL);
1262 assert(rsa); // couldn't make key pair
1263
1264 EVP_PKEY* privkey = EVP_PKEY_new();
1265 assert(privkey);
1266 ret = EVP_PKEY_set1_RSA(privkey, rsa);
1267 assert(ret);
1268
1269 X509* cert = X509_new();
1270 assert(cert);
1271
1272 X509_NAME* subject = X509_NAME_new();
1273 X509_EXTENSION* ext = X509_EXTENSION_new();
1274
1275 // set version to X509v3 (starts from 0)
1276 X509_set_version(cert, 2L);
1277
1278 int serial = Random::getRandom(); // get an int worth of randomness
1279 assert(sizeof(int)==4);
1280 ASN1_INTEGER_set(X509_get_serialNumber(cert),serial);
1281
1282 ret = X509_NAME_add_entry_by_txt( subject, "O", MBSTRING_UTF8,
1283 (unsigned char *) domain.data(), domain.size(),
1284 -1, 0);
1285 assert(ret);
1286 ret = X509_NAME_add_entry_by_txt( subject, "CN", MBSTRING_UTF8,
1287 (unsigned char *) aor.data(), aor.size(),
1288 -1, 0);
1289 assert(ret);
1290
1291 ret = X509_set_issuer_name(cert, subject);
1292 assert(ret);
1293 ret = X509_set_subject_name(cert, subject);
1294 assert(ret);
1295
1296 const long duration = 60*60*24*expireDays;
1297 X509_gmtime_adj(X509_get_notBefore(cert),0);
1298 X509_gmtime_adj(X509_get_notAfter(cert), duration);
1299
1300 ret = X509_set_pubkey(cert, privkey);
1301 assert(ret);
1302
1303 Data subjectAltNameStr = Data("URI:sip:") + aor
1304 + Data(",URI:im:")+aor
1305 + Data(",URI:pres:")+aor;
1306 ext = X509V3_EXT_conf_nid( NULL , NULL , NID_subject_alt_name,
1307 (char*) subjectAltNameStr.c_str() );
1308 X509_add_ext( cert, ext, -1);
1309 X509_EXTENSION_free(ext);
1310
1311 ext = X509V3_EXT_conf_nid(NULL, NULL, NID_basic_constraints, "CA:FALSE");
1312 ret = X509_add_ext( cert, ext, -1);
1313 assert(ret);
1314 X509_EXTENSION_free(ext);
1315
1316 // TODO add extensions NID_subject_key_identifier and NID_authority_key_identifier
1317
1318 ret = X509_sign(cert, privkey, EVP_sha1());
1319 assert(ret);
1320
1321 addCertX509( UserCert, aor, cert, true /* write */ );
1322 addPrivateKeyPKEY( UserPrivateKey, aor, privkey, true /* write */ );
1323 }
1324
1325
1326 MultipartSignedContents*
1327 BaseSecurity::sign(const Data& senderAor, Contents* contents)
1328 {
1329 assert( contents );
1330
1331 // form the multipart
1332 MultipartSignedContents* multi = new MultipartSignedContents;
1333 multi->header(h_ContentType).param( p_micalg ) = "sha1";
1334 multi->header(h_ContentType).param( p_protocol ) = "application/pkcs7-signature";
1335
1336 // add the main body to it
1337 Contents* body = contents->clone();
1338 multi->parts().push_back( body );
1339
1340 Data bodyData;
1341 DataStream strm( bodyData );
1342 body->encodeHeaders( strm );
1343 body->encode( strm );
1344 strm.flush();
1345
1346 DebugLog( << "signing data <" << bodyData.escaped() << ">" );
1347 Security::dumpAsn("resip-sign-out-data",bodyData);
1348
1349 const char* p = bodyData.data();
1350 int s = bodyData.size();
1351 BIO* in=BIO_new_mem_buf( (void*)p,s);
1352 assert(in);
1353 DebugLog( << "created in BIO");
1354
1355 BIO* out = BIO_new(BIO_s_mem()); // TODO - mem leak
1356 assert(out);
1357 DebugLog( << "created out BIO" );
1358
1359 STACK_OF(X509)* chain = sk_X509_new_null();
1360 assert(chain);
1361
1362 DebugLog( << "searching for cert/key for <" << senderAor << ">" );
1363 if (mUserCerts.count(senderAor) == 0 ||
1364 mUserPrivateKeys.count(senderAor) == 0)
1365 {
1366 WarningLog (<< "Tried to sign with no cert or private key for " << senderAor);
1367 throw Exception("No cert or private key to sign with",__FILE__,__LINE__);
1368 }
1369
1370 X509* publicCert = mUserCerts[senderAor];
1371 EVP_PKEY* privateKey = mUserPrivateKeys[senderAor];
1372
1373 int rv = X509_check_private_key(publicCert, privateKey);
1374 assert(rv);
1375
1376 // compute the signature
1377 int flags = 0;
1378 flags |= PKCS7_BINARY;
1379 flags |= PKCS7_DETACHED;
1380 flags |= PKCS7_NOCERTS;
1381 flags |= PKCS7_NOATTR;
1382 flags |= PKCS7_NOSMIMECAP;
1383
1384 PKCS7* pkcs7 = PKCS7_sign( publicCert, privateKey, chain, in, flags);
1385 if ( !pkcs7 )
1386 {
1387 ErrLog( << "Error creating PKCS7 signature object" );
1388 return 0;
1389 }
1390 DebugLog( << "created PKCS7 signature object " );
1391
1392 i2d_PKCS7_bio(out,pkcs7);
1393 BIO_flush(out);
1394
1395 char* outBuf=0;
1396 long size = BIO_get_mem_data(out,&outBuf);
1397 assert( size > 0 );
1398
1399 Data outData(outBuf,size);
1400 Security::dumpAsn("resip-sign-out-sig",outData);
1401
1402 Pkcs7SignedContents* sigBody = new Pkcs7SignedContents( outData );
1403 assert( sigBody );
1404
1405 // add the signature to it
1406 sigBody->header(h_ContentType).param( p_name ) = "smime.p7s";
1407 sigBody->header(h_ContentDisposition).param( p_handling ) = "required";
1408 sigBody->header(h_ContentDisposition).param( p_filename ) = "smime.p7s";
1409 sigBody->header(h_ContentDisposition).value() = "attachment" ;
1410 sigBody->header(h_ContentTransferEncoding).value() = "binary";
1411 multi->parts().push_back( sigBody );
1412
1413 assert( multi->parts().size() == 2 );
1414
1415 return multi;
1416 }
1417
1418
1419 Pkcs7Contents*
1420 BaseSecurity::encrypt(Contents* bodyIn, const Data& recipCertName )
1421 {
1422 assert( bodyIn );
1423
1424 int flags = 0 ;
1425 flags |= PKCS7_BINARY;
1426 flags |= PKCS7_NOCERTS;
1427
1428 Data bodyData;
1429 DataStream strm(bodyData);
1430 bodyIn->encodeHeaders(strm);
1431 bodyIn->encode( strm );
1432 strm.flush();
1433
1434 InfoLog( << "body data to encrypt is <" << bodyData.escaped() << ">" );
1435
1436 const char* p = bodyData.data();
1437 int s = bodyData.size();
1438
1439 BIO* in = BIO_new_mem_buf( (void*)p,s);
1440 assert(in);
1441 DebugLog( << "created in BIO");
1442
1443 BIO* out = BIO_new(BIO_s_mem());
1444 assert(out);
1445 DebugLog( << "created out BIO" );
1446
1447 InfoLog( << "target cert name is <" << recipCertName << ">" );
1448 if (mUserCerts.count(recipCertName) == 0)
1449 {
1450 WarningLog (<< "Tried to encrypt with no cert or private key for " << recipCertName);
1451 throw Exception("No cert or private key to encrypt with",__FILE__,__LINE__);
1452 }
1453
1454 X509* cert = mUserCerts[recipCertName];
1455 assert(cert);
1456
1457 STACK_OF(X509) *certs = sk_X509_new_null();
1458 assert(certs);
1459 sk_X509_push(certs, cert);
1460
1461 // if you think you need to change the following few lines, please email fluffy
1462 // the value of OPENSSL_VERSION_NUMBER ( in opensslv.h ) and the signature of
1463 // PKCS_encrypt found ( in pkcs7.h ) and the OS you are using
1464 #if ( OPENSSL_VERSION_NUMBER > 0x009060ffL )
1465 // const EVP_CIPHER* cipher = EVP_des_ede3_cbc();
1466 const EVP_CIPHER* cipher = EVP_aes_128_cbc();
1467 #else
1468 //const EVP_CIPHER* cipher = EVP_enc_null();
1469 EVP_CIPHER* cipher = EVP_des_ede3_cbc();
1470 #endif
1471 assert( cipher );
1472
1473 #if (OPENSSL_VERSION_NUMBER < 0x0090705fL )
1474 #warning PKCS7_encrypt() is broken in OpenSSL 0.9.7d
1475 #endif
1476
1477 PKCS7* pkcs7 = PKCS7_encrypt( certs, in, cipher, flags);
1478 if ( !pkcs7 )
1479 {
1480 ErrLog( << "Error creating PKCS7 encrypt object" );
1481 //throw Exception("Can't encrypt",__FILE__,__LINE__);
1482 return 0;
1483 }
1484 DebugLog( << "created PKCS7 encrypt object " );
1485
1486 i2d_PKCS7_bio(out,pkcs7);
1487
1488 BIO_flush(out);
1489
1490 char* outBuf=0;
1491 long size = BIO_get_mem_data(out,&outBuf);
1492 assert( size > 0 );
1493
1494 Data outData(outBuf,size);
1495 assert( (long)outData.size() == size );
1496
1497 InfoLog( << "Encrypted body size is " << outData.size() );
1498 InfoLog( << "Encrypted body is <" << outData.escaped() << ">" );
1499
1500 Security::dumpAsn("resip-encrypt-out",outData);
1501
1502 Pkcs7Contents* outBody = new Pkcs7Contents( outData );
1503 assert( outBody );
1504
1505 outBody->header(h_ContentType).param( p_smimeType ) = "enveloped-data";
1506 outBody->header(h_ContentType).param( p_name ) = "smime.p7m";
1507 outBody->header(h_ContentDisposition).param( p_handling ) = "required";
1508 outBody->header(h_ContentDisposition).param( p_filename ) = "smime.p7";
1509 outBody->header(h_ContentDisposition).value() = "attachment" ;
1510 outBody->header(h_ContentTransferEncoding).value() = "binary";
1511
1512 return outBody;
1513 }
1514
1515
1516 MultipartSignedContents *
1517 BaseSecurity::signAndEncrypt( const Data& senderAor, Contents* body, const Data& recipCertName )
1518 {
1519 //assert(0);
1520 //return 0;
1521 return sign(senderAor, encrypt(body, recipCertName));
1522 }
1523
1524
1525 Data
1526 BaseSecurity::computeIdentity( const Data& signerDomain, const Data& in ) const
1527 {
1528 DebugLog( << "Compute identity for " << in );
1529
1530 if (mDomainPrivateKeys.count(signerDomain) == 0)
1531 {
1532 ErrLog( << "No private key for " << signerDomain );
1533 throw Exception("Missing private key when computing identity",__FILE__,__LINE__);
1534 }
1535
1536 EVP_PKEY* pKey = mDomainPrivateKeys[signerDomain];
1537 assert( pKey );
1538
1539 if ( pKey->type != EVP_PKEY_RSA )
1540 {
1541 ErrLog( << "Private key (type=" << pKey->type <<"for "
1542 << signerDomain << " is not of type RSA" );
1543 throw Exception("No RSA private key when computing identity",__FILE__,__LINE__);
1544 }
1545
1546 assert( pKey->type == EVP_PKEY_RSA );
1547 RSA* rsa = EVP_PKEY_get1_RSA(pKey);
1548
1549 unsigned char result[4096];
1550 int resultSize = sizeof(result);
1551 assert( resultSize >= RSA_size(rsa) );
1552
1553 SHA1Stream sha;
1554 sha << in;
1555 Data hashRes = sha.getBin();
1556 DebugLog( << "hash of string is 0x" << hashRes.hex() );
1557
1558 #if 1
1559 int r = RSA_sign(NID_sha1, (unsigned char *)hashRes.data(), hashRes.size(),
1560 result, (unsigned int*)( &resultSize ),
1561 rsa);
1562 assert( r == 1 );
1563 #else
1564 resultSize = RSA_private_encrypt(hashResLen, hashRes,
1565 result, rsa, RSA_PKCS1_PADDING);
1566 if ( resultSize == -1 )
1567 {
1568 DebugLog( << "Problem doing RSA encrypt for identity");
1569 while (1)
1570 {
1571 const char* file;
1572 int line;
1573
1574 unsigned long code = ERR_get_error_line(&file,&line);
1575 if ( code == 0 )
1576 {
1577 break;
1578 }
1579
1580 char buf[256];
1581 ERR_error_string_n(code,buf,sizeof(buf));
1582 ErrLog( << buf );
1583 InfoLog( << "Error code = " << code << " file="<<file<<" line=" << line );
1584 }
1585
1586 return Data::Empty;
1587 }
1588 #endif
1589
1590 Data res(result,resultSize);
1591 DebugLog( << "rsa encrypt of hash is 0x"<< res.hex() );
1592
1593 Data enc = res.base64encode();
1594
1595 Security::dumpAsn("identity-in", in );
1596 Security::dumpAsn("identity-in-hash", hashRes );
1597 Security::dumpAsn("identity-in-rsa",res);
1598 Security::dumpAsn("identity-in-base64",enc);
1599
1600 return enc;
1601 }
1602
1603
1604 bool
1605 BaseSecurity::checkIdentity( const Data& signerDomain, const Data& in, const Data& sigBase64, X509* pCert ) const
1606 {
1607 X509* cert = pCert;
1608 if (!cert)
1609 {
1610 if (mDomainCerts.count(signerDomain) == 0)
1611 {
1612 ErrLog( << "No public key for " << signerDomain );
1613 throw Exception("Missing public key when verifying identity",__FILE__,__LINE__);
1614 }
1615 cert = mDomainCerts[signerDomain];
1616 }
1617
1618 DebugLog( << "Check identity for " << in );
1619 DebugLog( << " base64 data is " << sigBase64 );
1620
1621 Data sig = sigBase64.base64decode();
1622 DebugLog( << "decoded sig is 0x"<< sig.hex() );
1623
1624 SHA1Stream sha;
1625 sha << in;
1626 Data hashRes = sha.getBin();
1627 DebugLog( << "hash of string is 0x" << hashRes.hex() );
1628
1629 EVP_PKEY* pKey = X509_get_pubkey( cert );
1630 assert( pKey );
1631
1632 assert( pKey->type == EVP_PKEY_RSA );
1633 RSA* rsa = EVP_PKEY_get1_RSA(pKey);
1634
1635 #if 1
1636 int ret = RSA_verify(NID_sha1, (unsigned char *)hashRes.data(),
1637 hashRes.size(), (unsigned char*)sig.data(), sig.size(),
1638 rsa);
1639 #else
1640 unsigned char result[4096];
1641 int resultSize = sizeof(result);
1642 assert( resultSize >= RSA_size(rsa) );
1643
1644 resultSize = RSA_public_decrypt(sig.size(),(unsigned char*)sig.data(),
1645 result, rsa, RSA_PKCS1_PADDING );
1646 assert( resultSize != -1 );
1647 //assert( resultSize == SHA_DIGEST_LENGTH );
1648 Data recievedHash(result,resultSize);
1649 dumpAsn("identity-out-decrypt", recievedHash );
1650
1651 bool ret = ( computedHash == recievedHash );
1652 #endif
1653
1654 DebugLog( << "rsa verify result is " << ret );
1655
1656 dumpAsn("identity-out-msg", in );
1657 dumpAsn("identity-out-base64", sigBase64 );
1658 dumpAsn("identity-out-sig", sig );
1659 dumpAsn("identity-out-hash", hashRes );
1660
1661 return (ret != 0);
1662 }
1663
1664
1665 void
1666 BaseSecurity::checkAndSetIdentity( const SipMessage& msg, const Data& certDer) const
1667 {
1668 auto_ptr<SecurityAttributes> sec(new SecurityAttributes);
1669 X509* cert=NULL;
1670
1671 try
1672 {
1673 if ( !certDer.empty() )
1674 {
1675 #if (OPENSSL_VERSION_NUMBER < 0x0090800fL )
1676 unsigned char* in = (unsigned char*)certDer.data();
1677 #else
1678 unsigned const char* in = (unsigned const char*)certDer.data();
1679 #endif
1680 if (d2i_X509(&cert,&in,certDer.size()) == 0)
1681 {
1682 DebugLog(<< "Could not read DER certificate from " << certDer );
1683 cert = NULL;
1684 }
1685 }
1686 if ( certDer.empty() || cert )
1687 {
1688 if ( checkIdentity(msg.header(h_From).uri().host(),
1689 msg.getCanonicalIdentityString(),
1690 msg.header(h_Identity).value(),
1691 cert ) )
1692 {
1693 sec->setIdentity(msg.header(h_From).uri().getAor());
1694 sec->setIdentityStrength(SecurityAttributes::Identity);
1695 }
1696 else
1697 {
1698 sec->setIdentity(msg.header(h_From).uri().getAor());
1699 sec->setIdentityStrength(SecurityAttributes::FailedIdentity);
1700 }
1701 }
1702 else
1703 {
1704 sec->setIdentity(msg.header(h_From).uri().getAor());
1705 sec->setIdentityStrength(SecurityAttributes::FailedIdentity);
1706 }
1707 }
1708 catch (BaseException&)
1709 {
1710 sec->setIdentity(msg.header(h_From).uri().getAor());
1711 sec->setIdentityStrength(SecurityAttributes::FailedIdentity);
1712 }
1713 msg.setSecurityAttributes(sec);
1714 }
1715
1716
1717 Contents*
1718 BaseSecurity::decrypt( const Data& decryptorAor, const Pkcs7Contents* contents)
1719 {
1720
1721 DebugLog( << "decryptor Aor: <" << decryptorAor << ">" );
1722
1723 int flags=0;
1724 flags |= PKCS7_BINARY;
1725
1726 // for now, assume that this is only a singed message
1727 assert( contents );
1728
1729 Data text = contents->getBodyData();
1730 DebugLog( << "uncode body = <" << text.escaped() << ">" );
1731 DebugLog( << "uncode body size = " << text.size() );
1732
1733 Security::dumpAsn("resip-asn-decrypt", text );
1734
1735 BIO* in = BIO_new_mem_buf( (void*)text.c_str(), text.size());
1736 assert(in);
1737 InfoLog( << "created in BIO");
1738
1739 BIO* out;
1740 out = BIO_new(BIO_s_mem());
1741 assert(out);
1742 InfoLog( << "created out BIO" );
1743
1744 PKCS7* pkcs7 = d2i_PKCS7_bio(in, 0);
1745 if ( !pkcs7 )
1746 {
1747 ErrLog( << "Problems doing decode of PKCS7 object" );
1748
1749 while (1)
1750 {
1751 const char* file;
1752 int line;
1753
1754 unsigned long code = ERR_get_error_line(&file,&line);
1755 if ( code == 0 )
1756 {
1757 break;
1758 }
1759
1760 char buf[256];
1761 ERR_error_string_n(code,buf,sizeof(buf));
1762 ErrLog( << buf );
1763 InfoLog( << "Error code = " << code << " file=" << file << " line=" << line );
1764 }
1765
1766 return 0;
1767 }
1768 BIO_flush(in);
1769
1770 int type=OBJ_obj2nid(pkcs7->type);
1771 switch (type)
1772 {
1773 case NID_pkcs7_signed:
1774 InfoLog( << "data is pkcs7 signed" );
1775 break;
1776 case NID_pkcs7_signedAndEnveloped:
1777 InfoLog( << "data is pkcs7 signed and enveloped" );
1778 break;
1779 case NID_pkcs7_enveloped:
1780 InfoLog( << "data is pkcs7 enveloped" );
1781 break;
1782 case NID_pkcs7_data:
1783 InfoLog( << "data i pkcs7 data" );
1784 break;
1785 case NID_pkcs7_encrypted:
1786 InfoLog( << "data is pkcs7 encrypted " );
1787 break;
1788 case NID_pkcs7_digest:
1789 InfoLog( << "data is pkcs7 digest" );
1790 break;
1791 default:
1792 InfoLog( << "Unkown pkcs7 type" );
1793 break;
1794 }
1795
1796 STACK_OF(X509)* certs = sk_X509_new_null();
1797 assert( certs );
1798
1799 // flags |= PKCS7_NOVERIFY;
1800
1801 assert( mRootCerts );
1802
1803 switch (type)
1804 {
1805 case NID_pkcs7_signedAndEnveloped:
1806 {
1807 throw Exception("Signed and enveloped is not supported", __FILE__, __LINE__);
1808 }
1809 break;
1810
1811 case NID_pkcs7_enveloped:
1812 {
1813 if (mUserPrivateKeys.count(decryptorAor) == 0)
1814 {
1815 InfoLog( << "Don't have a private key for " << decryptorAor << " for PKCS7_decrypt" );
1816 throw Exception("Missing private key", __FILE__, __LINE__);
1817 }
1818 else if (mUserCerts.count(decryptorAor) == 0)
1819 {
1820 InfoLog( << "Don't have a public cert for " << decryptorAor << " for PKCS7_decrypt" );
1821 throw Exception("Missing cert", __FILE__, __LINE__);
1822 }
1823
1824 EVP_PKEY* privateKey = mUserPrivateKeys[decryptorAor];
1825 X509* publicCert = mUserCerts[decryptorAor];
1826
1827 if ( PKCS7_decrypt(pkcs7, privateKey, publicCert, out, flags ) != 1 )
1828 {
1829 ErrLog( << "Problems doing PKCS7_decrypt" );
1830 while (1)
1831 {
1832 const char* file;
1833 int line;
1834
1835 unsigned long code = ERR_get_error_line(&file,&line);
1836 if ( code == 0 )
1837 {
1838 break;
1839 }
1840
1841 char buf[256];
1842 ERR_error_string_n(code,buf,sizeof(buf));
1843 ErrLog( << buf );
1844 InfoLog( << "Error code = " << code << " file=" << file << " line=" << line );
1845 }
1846
1847 return 0;
1848 }
1849 }
1850 break;
1851
1852 default:
1853 ErrLog(<< "Got PKCS7 data that could not be handled type=" << type );
1854 throw Exception("Unsupported PKCS7 data type", __FILE__, __LINE__);
1855 }
1856
1857 BIO_flush(out);
1858 BUF_MEM* bufMem;
1859 BIO_get_mem_ptr(out, &bufMem);
1860
1861 int len = bufMem->length;
1862 char* buffer = new char[len];
1863 memcpy(buffer, bufMem->data, len);
1864
1865 BIO_set_close(out, BIO_CLOSE);
1866 BIO_free(out);
1867
1868 // parse out the header information and form new body.
1869 // TODO !jf! this is a really crappy parser - shoudl do proper mime stuff
1870 ParseBuffer pb(buffer, len);
1871
1872 const char* headerStart = pb.position();
1873
1874 // pull out contents type only
1875 pb.skipToChars("Content-Type");
1876 pb.assertNotEof();
1877
1878 pb.skipToChar(Symbols::COLON[0]);
1879 pb.skipChar();
1880 pb.assertNotEof();
1881
1882 pb.skipWhitespace();
1883 const char* typeStart = pb.position();
1884 pb.assertNotEof();
1885
1886 // determine contents-type header buffer
1887 pb.skipToTermCRLF();
1888 pb.assertNotEof();
1889
1890 ParseBuffer subPb(typeStart, pb.position() - typeStart);
1891 Mime contentType;
1892 contentType.parse(subPb);
1893
1894 pb.assertNotEof();
1895
1896 // determine body start
1897 pb.reset(typeStart);
1898 const char* bodyStart = pb.skipToChars(Symbols::CRLFCRLF);
1899 pb.assertNotEof();
1900 bodyStart += 4;
1901
1902 // determine contents body buffer
1903 pb.skipToEnd();
1904 Data tmp;
1905 pb.data(tmp, bodyStart);
1906 // create contents against body
1907 Contents* ret = Contents::createContents(contentType, tmp);
1908 ret->addBuffer(buffer);
1909
1910 // pre-parse headers
1911 ParseBuffer headersPb(headerStart, bodyStart-4-headerStart);
1912 ret->preParseHeaders(headersPb);
1913
1914 InfoLog( << "Got body data of " << ret->getBodyData() );
1915
1916 return ret;
1917 }
1918
1919
1920
1921
1922
1923 Contents*
1924 BaseSecurity::checkSignature(MultipartSignedContents* multi,
1925 Data* signedBy,
1926 SignatureStatus* sigStat )
1927 {
1928 if ( multi->parts().size() != 2 )
1929 {
1930 ErrLog(<< "Trying to decode a message with wrong number of contents " << multi->parts().size());
1931 throw Exception("Invalid contents passed to checkSignature", __FILE__, __LINE__);
1932 }
1933
1934 MultipartSignedContents::Parts::const_iterator it = multi->parts().begin();
1935 Contents* first = *it;
1936 ++it;
1937 assert( it != multi->parts().end() );
1938 Contents* second = *it;
1939
1940 assert( second );
1941 assert( first );
1942
1943 InfoLog( << "message to signature-check is " << *first );
1944
1945 Pkcs7SignedContents* sig = dynamic_cast<Pkcs7SignedContents*>( second );
1946 if ( !sig )
1947 {
1948 ErrLog( << "Don't know how to deal with signature type " );
1949 //throw Exception("Invalid contents passed to checkSignature", __FILE__,
1950 //__LINE__);
1951 return first;
1952 }
1953 Data sigData = sig->getBodyData();
1954
1955 Data textData;
1956 DataStream strm( textData );
1957 first->encodeHeaders( strm );
1958 first->encode( strm );
1959 strm.flush();
1960
1961 InfoLog( << "text <" << textData.escaped() << ">" );
1962 InfoLog( << "signature <" << sigData.escaped() << ">" );
1963
1964 Security::dumpAsn( "resip-asn-uncode-signed-text", textData );
1965 Security::dumpAsn( "resip-asn-uncode-signed-sig", sigData );
1966
1967 BIO* in = BIO_new_mem_buf( (void*)sigData.data(),sigData.size());
1968 assert(in);
1969 InfoLog( << "created in BIO");
1970
1971 BIO* out = BIO_new(BIO_s_mem());
1972 assert(out);
1973 InfoLog( << "created out BIO" );
1974
1975 BIO* pkcs7Bio = BIO_new_mem_buf( (void*) textData.data(),textData.size());
1976 assert(pkcs7Bio);
1977 InfoLog( << "created pkcs7 BIO");
1978
1979 PKCS7* pkcs7 = d2i_PKCS7_bio(in, 0);
1980 if ( !pkcs7 )
1981 {
1982 ErrLog( << "Problems doing decode of PKCS7 object <"
1983 << sigData.escaped() << ">" );
1984
1985 while (1)
1986 {
1987 const char* file;
1988 int line;
1989
1990 unsigned long code = ERR_get_error_line(&file,&line);
1991 if ( code == 0 )
1992 {
1993 break;
1994 }
1995
1996 char buf[256];
1997 ERR_error_string_n(code,buf,sizeof(buf));
1998 ErrLog( << buf );
1999 InfoLog( <<"Error code = "<< code <<" file=" << file << " line=" << line );
2000 }
2001
2002 return first;
2003 }
2004 BIO_flush(in);
2005
2006 int type=OBJ_obj2nid(pkcs7->type);
2007 switch (type)
2008 {
2009 case NID_pkcs7_signed:
2010 InfoLog( << "data is pkcs7 signed" );
2011 break;
2012 case NID_pkcs7_signedAndEnveloped:
2013 InfoLog( << "data is pkcs7 signed and enveloped" );
2014 break;
2015 case NID_pkcs7_enveloped:
2016 InfoLog( << "data is pkcs7 enveloped" );
2017 break;
2018 case NID_pkcs7_data:
2019 InfoLog( << "data is pkcs7 data" );
2020 break;
2021 case NID_pkcs7_encrypted:
2022 InfoLog( << "data is pkcs7 encrypted " );
2023 break;
2024 case NID_pkcs7_digest:
2025 InfoLog( << "data is pkcs7 digest" );
2026 break;
2027 default:
2028 InfoLog( << "Unknown pkcs7 type" );
2029 break;
2030 }
2031
2032 STACK_OF(X509)* certs = 0;
2033 certs = sk_X509_new_null();
2034 assert( certs );
2035
2036 if ( *signedBy == Data::Empty )
2037 {
2038 //add all the certificates from mUserCerts stack to 'certs' stack
2039 for(X509Map::iterator it = mUserCerts.begin(); it != mUserCerts.end(); it++)
2040 {
2041 assert(it->second);
2042 sk_X509_push(certs, it->second);
2043 }
2044 }
2045 else
2046 {
2047 if (mUserCerts.count( *signedBy ))
2048 {
2049 InfoLog( <<"Adding cert from " << *signedBy << " to check sig" );
2050 X509* cert = mUserCerts[ *signedBy ];
2051 assert(cert);
2052 sk_X509_push(certs, cert);
2053 }
2054 }
2055
2056 int flags = 0;
2057 flags |= PKCS7_NOINTERN;
2058
2059 // matches on certificate issuer and serial number - they must be unique
2060 STACK_OF(X509)* signers = PKCS7_get0_signers(pkcs7, certs, flags);
2061 if ( signers )
2062 {
2063
2064 DebugLog( << "Found " << sk_X509_num(signers) << " signers." );
2065 for (int i=0; i<sk_X509_num(signers); i++)
2066 {
2067 X509* x = sk_X509_value(signers, i);
2068 InfoLog(<< "Got a signer <" << i << "> : " << getCertName(x) );
2069
2070 GENERAL_NAMES* gens = 0;
2071 gens = (GENERAL_NAMES*)X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
2072
2073 for (int j = 0; j < sk_GENERAL_NAME_num(gens); j++)
2074 {
2075 GENERAL_NAME* gen = sk_GENERAL_NAME_value(gens, j);
2076 if (gen->type == GEN_URI)
2077 {
2078 ASN1_IA5STRING* uri = gen->d.uniformResourceIdentifier;
2079 Data name(uri->data, uri->length);
2080 InfoLog(<< "subjectAltName of signing cert contains <" << name << ">" );
2081 try
2082 {
2083 Uri n(name);
2084 if ( n.scheme() == "sip" )
2085 {
2086 *signedBy = name;
2087 InfoLog(<< "choose <" << name << "> signature" );
2088 }
2089 }
2090 catch (...)
2091 {
2092 }
2093 }
2094 }
2095
2096 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
2097 }
2098 }
2099 else
2100 {
2101 *sigStat = SignatureIsBad;
2102 InfoLog(<< "No valid signers of this messages" );
2103 return first;
2104 }
2105
2106 #if 0
2107 // this is debugging information to get the serial number of the signed
2108 // information
2109 STACK_OF(PKCS7_SIGNER_INFO) *sinfos;
2110 PKCS7_SIGNER_INFO *si;
2111 PKCS7_ISSUER_AND_SERIAL *ias;
2112 ASN1_INTEGER* asnSerial;
2113 long longSerial;
2114 X509_NAME* name;
2115
2116 sinfos = PKCS7_get_signer_info(pkcs7);
2117 if ( sinfos )
2118 {
2119 int num = sk_PKCS7_SIGNER_INFO_num(sinfos);
2120 for ( int i=0; i<num; i++ )
2121 {
2122 si = sk_PKCS7_SIGNER_INFO_value (sinfos, i) ;
2123 ias = si->issuer_and_serial;
2124 name = ias->issuer;
2125 asnSerial = ias->serial;
2126 longSerial = ASN1_INTEGER_get( (ASN1_INTEGER*)asnSerial );
2127 InfoLog( << "Signed with serial " << hex << longSerial );
2128 InfoLog( << "Name " << name );
2129 }
2130 }
2131 #endif
2132
2133 assert( mRootCerts );
2134
2135 switch (type)
2136 {
2137 case NID_pkcs7_signed:
2138 {
2139 int flags = 0;
2140
2141 if (isSelfSigned(sk_X509_value(signers,0)))
2142 {
2143 flags |= PKCS7_NOVERIFY;
2144 }
2145
2146 if ( PKCS7_verify(pkcs7, certs, mRootCerts, pkcs7Bio, out, flags ) != 1 )
2147 {
2148 ErrLog( << "Problems doing PKCS7_verify" );
2149
2150 if ( sigStat )
2151 {
2152 *sigStat = SignatureIsBad;
2153 }
2154
2155 while (1)
2156 {
2157 const char* file;
2158 int line;
2159
2160 unsigned long code = ERR_get_error_line(&file,&line);
2161 if ( code == 0 )
2162 {
2163 break;
2164 }
2165
2166 char buf[256];
2167 ERR_error_string_n(code,buf,sizeof(buf));
2168 ErrLog( << buf );
2169 InfoLog( << "Error code = " << code << " file=" << file << " line=" << line );
2170 }
2171 return first;
2172 }
2173 if ( sigStat )
2174 {
2175 if ( (flags & PKCS7_NOVERIFY) )
2176 {
2177 if (isSelfSigned(sk_X509_value(signers,0)))
2178 {
2179 DebugLog( << "Signature is selfSigned");
2180 *sigStat = SignatureSelfSigned;
2181 }
2182 else
2183 {
2184 DebugLog( << "Signature is notTrusted" );
2185 *sigStat = SignatureNotTrusted;
2186 }
2187 }
2188 else
2189 {
2190 if (false) // !jf! TODO look for this cert in store
2191 {
2192 DebugLog( << "Signature is trusted" );
2193 *sigStat = SignatureTrusted;
2194 }
2195 else
2196 {
2197 DebugLog( << "Signature is caTrusted" );
2198 *sigStat = SignatureCATrusted;
2199 }
2200 }
2201 }
2202 }
2203 break;
2204
2205 default:
2206 ErrLog(<< "Got PKCS7 data that could not be handled type=" << type );
2207 return 0;
2208 }
2209
2210 BIO_flush(out);
2211 char* outBuf=0;
2212 long size = BIO_get_mem_data(out,&outBuf);
2213 assert( size >= 0 );
2214
2215 Data outData(outBuf,size);
2216 DebugLog( << "uncoded body is <" << outData.escaped() << ">" );
2217
2218 return first;
2219 }
2220
2221
2222 SSL_CTX*
2223 BaseSecurity::getTlsCtx ()
2224 {
2225 assert(mTlsCtx);
2226 return mTlsCtx;
2227 }
2228
2229
2230 SSL_CTX*
2231 BaseSecurity::getSslCtx ()
2232 {
2233 assert(mSslCtx);
2234 return mSslCtx;
2235 }
2236
2237 Data
2238 BaseSecurity::getCertName(X509 *cert)
2239 {
2240 X509_NAME *subj;
2241 int extcount;
2242
2243 assert(cert);
2244
2245 if ((extcount = X509_get_ext_count(cert)) > 0)
2246 {
2247 for (int i = 0; i < extcount; i++)
2248 {
2249 char *extstr;
2250 X509_EXTENSION *ext;
2251
2252 ext = X509_get_ext(cert, i);
2253 extstr = (char*) OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));
2254
2255 if (!strcmp(extstr, "subjectAltName"))
2256 {
2257 int j;
2258
2259 #if (OPENSSL_VERSION_NUMBER < 0x0090800fL )
2260 unsigned char *data;
2261 #else
2262 unsigned const char *data;
2263 #endif
2264
2265 STACK_OF(CONF_VALUE) *val;
2266 CONF_VALUE *nval;
2267 X509V3_EXT_METHOD *meth;
2268 void *ext_str = NULL;
2269
2270 if (!(meth = X509V3_EXT_get(ext)))
2271 break;
2272 data = ext->value->data;
2273
2274 #if (OPENSSL_VERSION_NUMBER > 0x00907000L)
2275 if (meth->it)
2276 ext_str = ASN1_item_d2i(NULL, &data, ext->value->length,
2277 ASN1_ITEM_ptr(meth->it));
2278 else
2279 ext_str = meth->d2i(NULL, &data, ext->value->length);
2280 #else
2281 ext_str = meth->d2i(NULL, &data, ext->value->length);
2282 #endif
2283 val = meth->i2v(meth, ext_str, NULL);
2284 for (j = 0; j < sk_CONF_VALUE_num(val); j++)
2285 {
2286 nval = sk_CONF_VALUE_value(val, j);
2287 if (!strcmp(nval->name, "DNS"))
2288 {
2289 //retrieve name, from nval->value
2290 return Data(nval->value);
2291 }
2292 }
2293 }
2294 }
2295 }
2296
2297 char cname[256];
2298 memset(cname, 0, sizeof cname);
2299
2300 if ((subj = X509_get_subject_name(cert)) &&
2301 X509_NAME_get_text_by_NID(subj, NID_commonName, cname, sizeof(cname)-1) > 0)
2302 {
2303 return Data(cname);
2304 }
2305
2306 ErrLog(<< "This certificate doesn't have neither subjectAltName nor commonName");
2307 return Data::Empty;
2308 }
2309 /**
2310 Matchtes subjectAltName and cnames
2311 @todo looks incomplete, make better
2312 */
2313 static int
2314 matchHostName(char *certName, const char *domainName)
2315 {
2316 const char *dot;
2317 dot = strchr(domainName, '.');
2318 if (dot == NULL)
2319 {
2320 char *pnt = strchr(certName, '.');
2321 /* hostname is not fully-qualified; unqualify the certName. */
2322 if (pnt != NULL)
2323 {
2324 *pnt = '\0';
2325 }
2326 }
2327 else
2328 {
2329 if (strncmp(certName, "*.", 2) == 0)
2330 {
2331 domainName = dot + 1;
2332 certName += 2;
2333 }
2334 }
2335 return !strcasecmp(certName, domainName);
2336 }
2337
2338 bool
2339 BaseSecurity::compareCertName(X509 *cert, const Data& domainName)
2340 {
2341 assert(cert);
2342
2343 Data certName = getCertName(cert);
2344 if(Data::Empty == certName)
2345 return false;
2346
2347 bool isMatching = matchHostName((char*)certName.c_str(), domainName.c_str()) ? true : false;
2348
2349 return isMatching;
2350 }
2351
2352 bool
2353 BaseSecurity::isSelfSigned(X509 *cert)
2354 {
2355 int iRet = X509_NAME_cmp(cert->cert_info->issuer, cert->cert_info->subject);
2356 return (iRet == 0);
2357 }
2358
2359 void
2360 BaseSecurity::dumpAsn( char* name, Data data)
2361 {
2362 #if 1 // !CJ! TODO turn off
2363 assert(name);
2364
2365 if (true) // dump asn.1 stuff to debug file
2366 {
2367 ofstream strm(name, std::ios_base::trunc);
2368 if ( !strm )
2369 {
2370 ErrLog( <<"Could not write to " << name );
2371 }
2372 else
2373 {
2374 strm.write( data.data() , data.size() );
2375 }
2376 strm.flush();
2377 }
2378 #endif
2379 }
2380
2381 X509*
2382 BaseSecurity::getDomainCert( const Data& domain )
2383 {
2384 return mDomainCerts[domain];
2385 }
2386
2387 EVP_PKEY*
2388 BaseSecurity::getDomainKey( const Data& domain )
2389 {
2390 return mDomainPrivateKeys[domain];
2391
2392 }
2393
2394 #endif
2395
2396
2397
2398
2399 /* ====================================================================
2400 * The Vovida Software License, Version 1.0
2401 *
2402 * Copyright (c) 2002-2005 Vovida Networks, Inc. All rights reserved.
2403 *
2404 * Redistribution and use in source and binary forms, with or without
2405 * modification, are permitted provided that the following conditions
2406 * are met:
2407 *
2408 * 1. Redistributions of source code must retain the above copyright
2409 * notice, this list of conditions and the following disclaimer.
2410 *
2411 * 2. Redistributions in binary form must reproduce the above copyright
2412 * notice, this list of conditions and the following disclaimer in
2413 * the documentation and/or other materials provided with the
2414 * distribution.
2415 *
2416 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
2417 * and "Vovida Open Communication Application Library (VOCAL)" must
2418 * not be used to endorse or promote products derived from this
2419 * software without prior written permission. For written
2420 * permission, please contact vocal@vovida.org.
2421 *
2422 * 4. Products derived from this software may not be called "VOCAL", nor
2423 * may "VOCAL" appear in their name, without prior written
2424 * permission of Vovida Networks, Inc.
2425 *
2426 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
2427 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2428 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
2429 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
2430 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
2431 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
2432 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2433 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2434 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
2435 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2436 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
2437 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
2438 * DAMAGE.
2439 *
2440 * ====================================================================
2441 *
2442 * This software consists of voluntary contributions made by Vovida
2443 * Networks, Inc. and many individuals on behalf of Vovida Networks,
2444 * Inc. For more information on Vovida Networks, Inc., please see
2445 * <http://www.vovida.org/>.
2446 *
2447 */

Properties

Name Value
svn:eol-style LF

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27