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

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

Parent Directory Parent Directory | Revision Log Revision Log


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

Properties

Name Value
svn:eol-style LF

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27