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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3604 - (show annotations) (download)
Tue Nov 23 07:15:40 2004 UTC (15 years, 2 months ago) by fluffy
File size: 53616 byte(s)
who knows
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/Socket.hxx"
21 #include "resiprocate/os/Timer.hxx"
22 #include "resiprocate/os/ParseBuffer.hxx"
23 #include "resiprocate/os/FileSystem.hxx"
24
25
26 #if defined(USE_SSL)
27
28 #if !defined(WIN32)
29 #include <sys/types.h>
30 #include <sys/uio.h>
31 #include <sys/fcntl.h>
32 #include <unistd.h>
33 #include <dirent.h>
34 #endif
35
36 #include <sys/types.h>
37 #include <openssl/e_os2.h>
38 #include <openssl/evp.h>
39 #include <openssl/crypto.h>
40 #include <openssl/err.h>
41 #include <openssl/pem.h>
42 #include <openssl/pkcs7.h>
43 #include <openssl/x509v3.h>
44 #include <openssl/ssl.h>
45
46 using namespace resip;
47 using namespace std;
48
49 #define RESIPROCATE_SUBSYSTEM Subsystem::SIP
50
51
52 static const Data rootCert("root_cert_");
53 static const Data domainCert("domain_cert_");
54 static const Data domainKey("domain_key_");
55 static const Data userCert("user_cert_");
56 static const Data userKey("user_key_");
57 static const Data pem(".pem");
58
59 static const Data pemTypePrefixes[] =
60 {
61 rootCert,
62 domainCert,
63 domainKey,
64 userCert,
65 userKey
66 };
67
68 Data
69 readIntoData(const Data& filename)
70 {
71 DebugLog( << "Trying to read file " << filename );
72
73 ifstream is;
74 is.open(filename.c_str(), ios::binary );
75 assert(is.is_open()); // TODO should thorw not assert
76
77 // get length of file:
78 is.seekg (0, ios::end);
79 int length = is.tellg();
80 is.seekg (0, ios::beg);
81
82 char* buffer = new char [length];
83
84 // read data as a block:
85 is.read (buffer,length);
86
87 Data target(Data::Take, buffer, length);
88
89 is.close();
90
91 return target;
92 }
93
94 Data
95 getAor(const Data& filename, const Data& prefix)
96 {
97 return filename.substr(prefix.size(), filename.size() - prefix.size() - pem.size());
98 }
99
100 Security::Security(const Data& directory) : mPath(directory)
101 {
102 }
103
104 void
105 Security::preload()
106 {
107 #if 0
108 FileSystem::Directory dir(mPath);
109 char buffer[8192];
110 Data fileT(Data::Borrow, buffer, sizeof(buffer));
111 FileSystem::Directory::iterator it(dir);
112 for (; it != dir.end(); ++it)
113 {
114 if (it->postfix(pem))
115 {
116 if (it->prefix(userCert))
117 {
118 addUserCertPEM(getAor(*it, userCert), readIntoData(*it));
119 }
120 else if (it->prefix(userKey))
121 {
122 addUserPrivateKeyPEM(getAor(*it, userKey), readIntoData(*it));
123 }
124 else if (it->prefix(domainCert))
125 {
126 addDomainPrivateKeyPEM(getAor(*it, domainCert), readIntoData(*it));
127 }
128 else if (it->prefix(domainKey))
129 {
130 addDomainPrivateKeyPEM(getAor(*it, domainKey), readIntoData(*it));
131 }
132 else if (it->prefix(rootCert))
133 {
134 addRootCertPEM(readIntoData(*it));
135 }
136 }
137 }
138 #else
139 DIR* dir = opendir( mPath.c_str() );
140
141 if (!dir )
142 {
143 ErrLog( << "Error reading public key directory " << mPath );
144 return;
145 }
146
147 struct dirent * d = 0;
148 while (1)
149 {
150 d = readdir(dir);
151 if ( !d )
152 {
153 break;
154 }
155
156 Data name( d->d_name );
157
158 if (name.postfix(pem))
159 {
160 if (name.prefix(userCert))
161 {
162 addUserCertPEM(getAor(name, userCert), readIntoData(mPath + name));
163 }
164 else if (name.prefix(userKey))
165 {
166 addUserPrivateKeyPEM(getAor(name, userKey), readIntoData(mPath + name));
167 }
168 else if (name.prefix(domainCert))
169 {
170 addDomainPrivateKeyPEM(getAor(name, domainCert), readIntoData(mPath + name));
171 }
172 else if (name.prefix(domainKey))
173 {
174 addDomainPrivateKeyPEM(getAor(name, domainKey), readIntoData(mPath + name));
175 }
176 else if (name.prefix(rootCert))
177 {
178 addRootCertPEM(readIntoData(mPath + name));
179 }
180 }
181 }
182 closedir( dir );
183 #endif
184
185 }
186
187 void
188 Security::onReadPEM(const Data& name, PEMType type, Data& buffer) const
189 {
190 Data filename = mPath + pemTypePrefixes[type] + name + pem;
191
192 // .dlb. extra copy
193 buffer = readIntoData(filename);
194 }
195
196 void
197 Security::onWritePEM(const Data& name, PEMType type, const Data& buffer) const
198 {
199 Data filename = mPath + pemTypePrefixes[type] + name + pem;
200
201 ofstream str(filename.c_str(), ios::binary);
202 str.write(buffer.data(), buffer.size());
203 }
204
205 void
206 Security::onRemovePEM(const Data& name, PEMType type) const
207 {
208 }
209
210
211
212 namespace
213 {
214
215 FILE* fopenHelper (const char* pathname, const char* option)
216 {
217 FILE* fp = fopen(pathname, option);
218
219 if ( !fp )
220 {
221 Data msg;
222 DataStream strm(msg);
223
224 strm << "fopen(" << pathname << ", " << option << ")" << "failed";
225
226 ErrLog(<< msg);
227 throw BaseSecurity::Exception(msg, __FILE__,__LINE__);
228 }
229
230 return fp;
231 }
232
233 void clearError ()
234 {
235 while (ERR_get_error())
236 ;
237 }
238 void onReadError (bool do_throw = false)
239 {
240 Data msg;
241 while (true)
242 {
243 const char* file;
244 int line;
245
246 unsigned long code = ERR_get_error_line(&file,&line);
247 if ( code == 0 )
248 {
249 break;
250 }
251
252 msg.clear();
253 DataStream strm(msg);
254 char err_str[256];
255 ERR_error_string_n(code, err_str, sizeof(err_str));
256 strm << err_str << ", file=" << file << ", line= " << line << ", error code=" << code;
257
258 ErrLog(<< msg);
259 }
260 if(do_throw)
261 throw BaseSecurity::Exception(msg, __FILE__,__LINE__);
262 }
263 void logReadError ()
264 {
265 onReadError(false);
266 }
267 void throwReadError ()
268 {
269 onReadError(true);
270 }
271
272 struct FileGuard
273 {
274 FileGuard (FILE* fp)
275 : mFp(fp) {}
276 ~FileGuard ()
277 {
278 fclose(mFp);
279 }
280
281 FILE* mFp;
282 };
283
284 #if defined(WIN32)
285
286 struct FindGuard
287 {
288 FindGuard (HANDLE findHandle)
289 : mHandle(findHandle) {}
290 ~FindGuard ()
291 {
292 FindClose(mHandle);
293 }
294
295 HANDLE mHandle;
296 };
297
298 #else
299
300 struct DirGuard
301 {
302 DirGuard (DIR* dir)
303 : mDir(dir) {}
304 ~DirGuard ()
305 {
306 closedir(mDir);
307 }
308
309 DIR* mDir;
310 };
311 #endif
312
313 // ------------------------------------------------------------
314 // OpenSSL certificate loading from PEM strings
315 //
316
317 // derived from openssl/crypto/x509/by_file.c : X509_load_cert_crl_file
318 //
319 int
320 pemstring_cert_crl(X509_LOOKUP *lu, const char *certPem)
321 {
322 BIO* in = BIO_new_mem_buf(const_cast<char*>(certPem), -1);
323
324 if(!in) {
325 X509err(X509_F_X509_LOAD_CERT_CRL_FILE,ERR_R_SYS_LIB);
326 return 0;
327 }
328 BIO_set_close(in, BIO_NOCLOSE);
329 STACK_OF(X509_INFO)* inf = PEM_X509_INFO_read_bio(in, NULL, NULL, NULL);
330 BIO_free(in);
331 if(!inf) {
332 X509err(X509_F_X509_LOAD_CERT_CRL_FILE,ERR_R_PEM_LIB);
333 return 0;
334 }
335
336 int count = 0;
337 for(int i = 0; i < sk_X509_INFO_num(inf); i++) {
338 X509_INFO* itmp = sk_X509_INFO_value(inf, i);
339 if(itmp->x509) {
340 X509_STORE_add_cert(lu->store_ctx, itmp->x509);
341 count++;
342 } else if(itmp->crl) {
343 X509_STORE_add_crl(lu->store_ctx, itmp->crl);
344 count++;
345 }
346 }
347 sk_X509_INFO_pop_free(inf, X509_INFO_free);
348 return count;
349 }
350
351 int
352 pemstring_ctrl(X509_LOOKUP *lu, int cmd, const char *argp, long argl, char **ret)
353 {
354 int ok = 0;
355
356 switch (cmd)
357 {
358 case X509_L_FILE_LOAD:
359 ok = (pemstring_cert_crl(lu,argp) != 0);
360 break;
361 }
362 return ok;
363 }
364 // ----------- END of OpenSSL support section ---------------
365
366 void configSslCtx (SSL_CTX* ctx, X509_STORE* certStore)
367 {
368 // associate root certs to mTlsCtx
369 int ret;
370 SSL_CTX_set_cert_store(ctx, certStore);
371 //assert(ret);
372
373 // set up the cipher
374 static char* cipher="RSA+SHA+AES+3DES";
375 ret = SSL_CTX_set_cipher_list(ctx,cipher);
376 assert(ret);
377 }
378
379
380 void
381 setPassPhrase(BaseSecurity::PassPhraseMap& passPhrases, const Data& key, const Data& passPhrase)
382 {
383 BaseSecurity::PassPhraseMap::iterator iter = passPhrases.find(key);
384 if (iter == passPhrases.end())
385 passPhrases.insert(std::make_pair(key, passPhrase));
386 }
387 bool
388 hasPassPhrase(const BaseSecurity::PassPhraseMap& passPhrases, const Data& key)
389 {
390 BaseSecurity::PassPhraseMap::const_iterator iter = passPhrases.find(key);
391 if (iter == passPhrases.end())
392 return false;
393 else
394 return true;
395 }
396
397
398 } // namespace
399
400
401
402 void
403 BaseSecurity::addCertDER (PEMType type, const Data& key, const Data& certDER, bool write)
404 {
405 assert( !certDER.empty() );
406 X509Map& certs = (type == DomainCert ? mDomainCerts : mUserCerts);
407
408 X509Map::iterator where = certs.find(key);
409 if (where == certs.end())
410 {
411 X509* cert;
412 unsigned char* in = reinterpret_cast<unsigned char*>(const_cast<char*>(certDER.data()));
413 if (d2i_X509(&cert,&in,certDER.size()) == 0)
414 {
415 ErrLog(<< "Could not read DER certificate from " << certDER );
416 throw BaseSecurity::Exception("Could not read DER certificate ", __FILE__,__LINE__);
417 }
418 certs.insert(std::make_pair(key, cert));
419
420 if (write)
421 {
422 // creates a read/write BIO buffer.
423 BIO *out = BIO_new(BIO_s_mem());
424 assert(out);
425 try
426 {
427 int ret = PEM_write_bio_X509(out, cert);
428 assert(ret);
429
430 BIO_flush(out);
431 // get content in BIO buffer to our buffer.
432 char* p = 0;
433 size_t len = BIO_get_mem_data(out,&p);
434 assert(p);
435 assert(len);
436 Data buf(Data::Take, p, len);
437
438 this->onWritePEM(key, type, buf);
439 }
440 catch(...)
441 {
442 BIO_free(out);
443 throw;
444 }
445 BIO_free(out);
446 }
447 }
448 }
449 void
450 BaseSecurity::addCertPEM (PEMType type, const Data& key, const Data& certPEM, bool write)
451 {
452 assert( !certPEM.empty() );
453 X509Map& certs = (type == DomainCert ? mDomainCerts : mUserCerts);
454
455 X509Map::iterator where = certs.find(key);
456 if (where == certs.end())
457 {
458 if (write)
459 this->onWritePEM(key, type, certPEM);
460
461 BIO* in = BIO_new_mem_buf(const_cast<char*>(certPEM.c_str()), -1);
462
463 if ( !in )
464 {
465 ErrLog(<< "Could not create BIO buffer from '" << certPEM << "'");
466 throw Exception("Could not create BIO buffer", __FILE__,__LINE__);
467 }
468
469 try
470 {
471 BIO_set_close(in, BIO_NOCLOSE);
472
473 X509* cert = PEM_read_bio_X509(in,0,0,0);
474 certs.insert(std::make_pair(key, cert));
475 }
476 catch(...)
477 {
478 BIO_free(in);
479 throw;
480 }
481 BIO_free(in);
482 }
483 }
484 bool
485 BaseSecurity::hasCert (PEMType type, const Data& key, bool read) const
486 {
487 assert( !key.empty() );
488 X509Map& certs = (type == DomainCert ? mDomainCerts : mUserCerts);
489
490 X509Map::iterator where = certs.find(key);
491 if (where == certs.end())
492 {
493 if (read)
494 {
495 Data certPEM;
496 try
497 {
498 onReadPEM(key, type, certPEM);
499 BaseSecurity* mutable_this = const_cast<BaseSecurity*>(this);
500 mutable_this->addCertPEM(type, key, certPEM, false);
501 return true;
502 }
503 catch (...)
504 {
505 return false;
506 }
507 }
508 else
509 {
510 return false;
511 }
512 }
513 return true;
514 }
515 bool
516 BaseSecurity::removeCert (PEMType type, const Data& key, bool remove)
517 {
518 assert( !key.empty() );
519 X509Map& certs = (type == DomainCert ? mDomainCerts : mUserCerts);
520
521 X509Map::iterator iter = certs.find(key);
522 if (iter != certs.end())
523 {
524 X509_free(iter->second);
525 certs.erase(iter);
526
527 if (remove)
528 onRemovePEM(key, type);
529
530 return true;
531 }
532 return false;
533 }
534 Data
535 BaseSecurity::getCertDER (PEMType type, const Data& key, bool read) const
536 {
537 assert( !key.empty() );
538
539 if (hasCert(type, key, read) == false)
540 {
541 ErrLog(<< "Could find certificate for '" << key << "'");
542 throw BaseSecurity::Exception("Could not find certificate", __FILE__,__LINE__);
543 }
544
545 X509Map& certs = (type == DomainCert ? mDomainCerts : mUserCerts);
546 BaseSecurity::X509Map::iterator where = certs.find(key);
547 if (where == certs.end())
548 {
549 // not supposed to happen,
550 // hasCert() should have inserted a value into certs
551 // or we should have throwed.
552 assert(0);
553 }
554
555 X509* x = where->second;
556 int len = i2d_X509(x, NULL);
557
558 // !kh!
559 // Although len == 0 is not an error, I am not sure what quite to do.
560 // Asserting for now.
561 assert(len != 0);
562 if(len < 0)
563 {
564 ErrLog(<< "Could encode certificate of '" << key << "' to DER form");
565 throw BaseSecurity::Exception("Could encode certificate to DER form", __FILE__,__LINE__);
566 }
567 char* out = new char[len];
568 return Data(Data::Take, out, len);
569 }
570
571
572
573 void
574 BaseSecurity::addPrivateKeyDER(
575 PEMType type,
576 const Data& key,
577 const Data& privateKeyDER,
578 bool write)
579 {
580 assert( !key.empty() );
581 assert( !privateKeyDER.empty() );
582
583 PrivateKeyMap& privateKeys = (type == DomainPrivateKey ? mDomainPrivateKeys : mUserPrivateKeys);
584
585 PrivateKeyMap::iterator where = privateKeys.find(key);
586 if (where == privateKeys.end())
587 {
588 if (write)
589 {
590 onWritePEM(key, type, privateKeyDER);
591 }
592 BIO* in = BIO_new_mem_buf(const_cast<char*>(privateKeyDER.c_str()), -1);
593
594 if ( !in )
595 {
596 ErrLog(<< "Could create BIO buffer from '" << privateKeyDER << "'");
597 throw Exception("Could not create BIO buffer", __FILE__,__LINE__);
598 }
599
600 try
601 {
602 char* p = 0;
603 if (type != DomainPrivateKey)
604 {
605 PassPhraseMap::const_iterator iter = mUserPassPhrases.find(key);
606 if(iter != mUserPassPhrases.end())
607 {
608 p = const_cast<char*>(iter->second.c_str());
609 }
610 }
611
612 BIO_set_close(in, BIO_NOCLOSE);
613
614 EVP_PKEY* privateKey;
615 if (d2i_PKCS8PrivateKey_bio(in, &privateKey, 0, p) == 0)
616 {
617 ErrLog(<< "Could not read private key from '" << privateKeyDER << "' using pass phrase '" << p << "'" );
618 throw Exception("Could not read private key ", __FILE__,__LINE__);
619 }
620
621 privateKeys.insert(std::make_pair(key, privateKey));
622 }
623 catch(...)
624 {
625 BIO_free(in);
626 throw;
627 }
628 BIO_free(in);
629 }
630 }
631
632 void
633 BaseSecurity::addPrivateKeyPEM(
634 PEMType type,
635 const Data& key,
636 const Data& privateKeyPEM,
637 bool write)
638 {
639 assert( !key.empty() );
640 assert( !privateKeyPEM.empty() );
641
642 PrivateKeyMap& privateKeys = (type == DomainPrivateKey ? mDomainPrivateKeys : mUserPrivateKeys);
643
644 PrivateKeyMap::iterator where = privateKeys.find(key);
645 if (where == privateKeys.end())
646 {
647 if (write)
648 {
649 onWritePEM(key, type, privateKeyPEM);
650 }
651 BIO* in = BIO_new_mem_buf(const_cast<char*>(privateKeyPEM.c_str()), -1);
652
653 if ( !in )
654 {
655 ErrLog(<< "Could create BIO buffer from '" << privateKeyPEM << "'");
656 throw Exception("Could not create BIO buffer", __FILE__,__LINE__);
657 }
658
659 try
660 {
661 char* p = 0;
662 if (type != DomainPrivateKey)
663 {
664 PassPhraseMap::const_iterator iter = mUserPassPhrases.find(key);
665 if(iter != mUserPassPhrases.end())
666 {
667 p = const_cast<char*>(iter->second.c_str());
668 }
669 }
670
671 BIO_set_close(in, BIO_NOCLOSE);
672
673 EVP_PKEY* privateKey;
674 if (PEM_read_bio_PrivateKey(in, &privateKey, 0, p) == 0)
675 {
676 ErrLog(<< "Could not read private key from '" << privateKeyPEM << "' using pass phrase '" << p << "'" );
677 throw Exception("Could not read private key ", __FILE__,__LINE__);
678 }
679
680 privateKeys.insert(std::make_pair(key, privateKey));
681 }
682 catch(...)
683 {
684 BIO_free(in);
685 throw;
686 }
687 BIO_free(in);
688 }
689 }
690 bool
691 BaseSecurity::hasPrivateKey(
692 PEMType type,
693 const Data& key,
694 bool read) const
695 {
696 assert( !key.empty() );
697
698 PrivateKeyMap& privateKeys = (type == DomainPrivateKey ? mDomainPrivateKeys : mUserPrivateKeys);
699
700 PrivateKeyMap::const_iterator where = privateKeys.find(key);
701 if (where == privateKeys.end())
702 {
703 if (read)
704 {
705 Data privateKeyPEM;
706 try
707 {
708 onReadPEM(key, type, privateKeyPEM);
709 BaseSecurity* mutable_this = const_cast<BaseSecurity*>(this);
710 mutable_this->addPrivateKeyPEM(type, key, privateKeyPEM, false);
711 }
712 catch(...)
713 {
714 return false;
715 }
716 return true;
717 }
718 return false;
719 }
720 else
721 {
722 return true;
723 }
724 }
725 Data
726 BaseSecurity::getPrivateKeyPEM(
727 PEMType type,
728 const Data& key,
729 bool read) const
730 {
731 assert( !key.empty() );
732
733 if (hasPrivateKey(type, key, true) == false)
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 // !kh!
753 // creates a read/write BIO buffer.
754 BIO *out = BIO_new(BIO_s_mem());
755 assert(out);
756 EVP_PKEY* pk = where->second;
757 assert(pk);
758
759 // write pk to out using key phrase p, with no cipher.
760 int ret = PEM_write_bio_PrivateKey(out, pk, 0, 0, 0, 0, p);
761 assert(ret == 1);
762
763 // get content in BIO buffer to our buffer.
764 // hand our buffer to a Data object.
765 BIO_flush(out);
766 char* buf = 0;
767 int len = BIO_get_mem_data(out, &buf);
768 return Data(Data::Take, buf, len);
769 }
770 Data
771 BaseSecurity::getPrivateKeyDER(
772 PEMType type,
773 const Data& key,
774 bool read) const
775 {
776 assert( !key.empty() );
777
778 if (hasPrivateKey(type, key, true) == false)
779 {
780 ErrLog(<< "Could find private key for '" << key << "'");
781 throw Exception("Could not find private key", __FILE__,__LINE__);
782 }
783
784 PrivateKeyMap& privateKeys = (type == DomainPrivateKey ? mDomainPrivateKeys : mUserPrivateKeys);
785
786 PrivateKeyMap::const_iterator where = privateKeys.find(key);
787 char* p = 0;
788 if (type != DomainPrivateKey)
789 {
790 PassPhraseMap::const_iterator iter = mUserPassPhrases.find(key);
791 if(iter != mUserPassPhrases.end())
792 {
793 p = const_cast<char*>(iter->second.c_str());
794 }
795 }
796
797 // !kh!
798 // creates a read/write BIO buffer.
799 BIO *out = BIO_new(BIO_s_mem());
800 assert(out);
801 EVP_PKEY* pk = where->second;
802 assert(pk);
803
804 // write pk to out using key phrase p, with no cipher.
805 int ret = i2d_PKCS8PrivateKey_bio(out, pk, 0, 0, 0, 0, p);
806 assert(ret == 1);
807
808 // get content in BIO buffer to our buffer.
809 // hand our buffer to a Data object.
810 BIO_flush(out);
811 char* buf = 0;
812 int len = BIO_get_mem_data(out, &buf);
813 return Data(Data::Take, buf, len);
814 }
815 bool
816 BaseSecurity::removePrivateKey(PEMType type, const Data& key, bool remove)
817 {
818 assert( !key.empty() );
819
820 PrivateKeyMap& privateKeys = (type == DomainPrivateKey ? mDomainPrivateKeys : mUserPrivateKeys);
821
822 assert( !key.empty() );
823 PrivateKeyMap::iterator iter = privateKeys.find(key);
824 if (iter != privateKeys.end())
825 {
826 EVP_PKEY_free(iter->second);
827 privateKeys.erase(iter);
828
829 onRemovePEM(key, type);
830 return true;
831 }
832 return false;
833 }
834
835
836
837
838
839 Security::Exception::Exception(const Data& msg, const Data& file, const int line)
840 : BaseException(msg,file,line)
841 {
842 }
843
844 BaseSecurity::BaseSecurity () :
845 mTlsCtx(0),
846 mSslCtx(0),
847 mRootCerts(0)
848 {
849 }
850 BaseSecurity::~BaseSecurity ()
851 {
852 {
853 // cleanup certificates
854 X509Map::iterator iter = mDomainCerts.begin();
855 for (; iter != mDomainCerts.end(); ++iter)
856 {
857 X509_free(iter->second);
858 mDomainCerts.erase(iter);
859 }
860 iter = mUserCerts.begin();
861 for (; iter != mUserCerts.end(); ++iter)
862 {
863 X509_free(iter->second);
864 mUserCerts.erase(iter);
865 }
866 }
867 {
868 // cleanup private keys
869 PrivateKeyMap::iterator iter = mDomainPrivateKeys.begin();
870 for (; iter != mDomainPrivateKeys.end(); ++iter)
871 {
872 EVP_PKEY_free(iter->second);
873 mDomainPrivateKeys.erase(iter);
874 }
875 iter = mUserPrivateKeys.begin();
876 for (; iter != mUserPrivateKeys.end(); ++iter)
877 {
878 EVP_PKEY_free(iter->second);
879 mUserPrivateKeys.erase(iter);
880 }
881 }
882 {
883 // cleanup root certs
884 X509_STORE_free(mRootCerts);
885 }
886 {
887 // cleanup SSL_CTXes
888 SSL_CTX_free(mTlsCtx);
889 SSL_CTX_free(mSslCtx);
890 }
891 }
892 void
893 BaseSecurity::initialize ()
894 {
895 DebugLog( << "Setting up SSL library" );
896
897 SSL_library_init();
898 SSL_load_error_strings();
899 OpenSSL_add_all_algorithms();
900 //OpenSSL_add_ssl_algorithms();
901 Random::initialize();
902 Timer::getTimeMs(); // initalize time offsets
903
904 // make sure that necessary algorithms exist:
905 assert(EVP_des_ede3_cbc());
906 }
907
908 std::vector<BaseSecurity::CertificateInfo>
909 BaseSecurity::getRootCertDescriptions() const
910 {
911 // !kh!
912 // need to be implemented.
913 assert(0);
914 return std::vector<CertificateInfo>();
915 }
916 void
917 BaseSecurity::addRootCertPEM(const Data& x509PEMEncodedRootCerts)
918 {
919 assert( !x509PEMEncodedRootCerts.empty() );
920
921 static X509_LOOKUP_METHOD x509_pemstring_lookup =
922 {
923 "Load cert from PEM string into cache",
924 NULL, /* new */
925 NULL, /* free */
926 NULL, /* init */
927 NULL, /* shutdown */
928 pemstring_ctrl,/* ctrl */
929 NULL, /* get_by_subject */
930 NULL, /* get_by_issuer_serial */
931 NULL, /* get_by_fingerprint */
932 NULL, /* get_by_alias */
933 };
934
935 if (mRootCerts == 0)
936 mRootCerts = X509_STORE_new();
937
938 assert( mRootCerts );
939
940 X509_LOOKUP* lookup = X509_STORE_add_lookup(mRootCerts, &x509_pemstring_lookup);
941
942 if (lookup == NULL)
943 throw Exception("Error in BaseSecurity::addRootCertPEM()", __FILE__,__LINE__);
944
945 // !kh!
946 // bug, no error handling here.
947 X509_LOOKUP_ctrl(lookup, X509_L_FILE_LOAD, x509PEMEncodedRootCerts.c_str(), 0, 0);
948 }
949
950 void
951 BaseSecurity::addDomainCertPEM(const Data& domainName, const Data& certPEM)
952 {
953 addCertPEM(DomainCert, domainName, certPEM, true);
954 }
955
956 void
957 BaseSecurity::addDomainCertDER(const Data& domainName, const Data& certDER)
958 {
959 addCertDER(DomainCert, domainName, certDER, true);
960 }
961
962 bool
963 BaseSecurity::hasDomainCert(const Data& domainName) const
964 {
965 return hasCert(DomainCert, domainName, true);
966 }
967
968 bool
969 BaseSecurity::removeDomainCert(const Data& domainName)
970 {
971 return removeCert(DomainCert, domainName, true);
972 }
973
974 Data
975 BaseSecurity::getDomainCertDER(const Data& domainName) const
976 {
977 return getCertDER(DomainCert, domainName, true);
978 }
979
980 void
981 BaseSecurity::addDomainPrivateKeyPEM(const Data& domainName, const Data& privateKeyPEM)
982 {
983 addPrivateKeyPEM(DomainPrivateKey, domainName, privateKeyPEM, true);
984 }
985 bool
986 BaseSecurity::hasDomainPrivateKey(const Data& domainName) const
987 {
988 return hasPrivateKey(DomainPrivateKey, domainName, true);
989 }
990 bool
991 BaseSecurity::removeDomainPrivateKey(const Data& domainName)
992 {
993 return removePrivateKey(DomainPrivateKey, domainName, true);
994 }
995 Data
996 BaseSecurity::getDomainPrivateKeyPEM(const Data& domainName) const
997 {
998 return getPrivateKeyPEM(DomainPrivateKey, domainName, true);
999 }
1000
1001 void
1002 BaseSecurity::addUserCertPEM(const Data& aor, const Data& certPEM)
1003 {
1004 addCertPEM(UserCert, aor, certPEM, true);
1005 }
1006 void
1007 BaseSecurity::addUserCertDER(const Data& aor, const Data& certDER)
1008 {
1009 addCertDER(UserCert, aor, certDER, true);
1010 }
1011 bool
1012 BaseSecurity::hasUserCert(const Data& aor) const
1013 {
1014 return hasCert(UserCert, aor, true);
1015 }
1016 bool
1017 BaseSecurity::removeUserCert(const Data& aor)
1018 {
1019 return removeCert(UserCert, aor, true);
1020 }
1021 Data
1022 BaseSecurity::getUserCertDER(const Data& aor) const
1023 {
1024 return getCertDER(UserCert, aor, true);
1025 }
1026
1027 void
1028 BaseSecurity::setUserPassPhrase(const Data& aor, const Data& passPhrase)
1029 {
1030 assert(aor.empty());
1031
1032 PassPhraseMap::iterator iter = mUserPassPhrases.find(aor);
1033 if(iter == mUserPassPhrases.end())
1034 mUserPassPhrases.insert(std::make_pair(aor, passPhrase));
1035 }
1036 bool
1037 BaseSecurity::hasUserPassPhrase(const Data& aor) const
1038 {
1039 assert(aor.empty());
1040
1041 PassPhraseMap::const_iterator iter = mUserPassPhrases.find(aor);
1042 if(iter == mUserPassPhrases.end())
1043 return false;
1044 else
1045 return true;
1046 }
1047 bool
1048 BaseSecurity::removeUserPassPhrase(const Data& aor)
1049 {
1050 assert(aor.empty());
1051
1052 PassPhraseMap::iterator iter = mUserPassPhrases.find(aor);
1053 if(iter == mUserPassPhrases.end())
1054 {
1055 return false;
1056 }
1057 else
1058 {
1059 mUserPassPhrases.erase(iter);
1060 return true;
1061 }
1062 }
1063 Data
1064 BaseSecurity::getUserPassPhrase(const Data& aor) const
1065 {
1066 assert(aor.empty());
1067
1068 PassPhraseMap::const_iterator iter = mUserPassPhrases.find(aor);
1069 if(iter == mUserPassPhrases.end())
1070 {
1071 return iter->second;
1072 }
1073 else
1074 {
1075 return Data::Empty;
1076 }
1077 }
1078
1079 void
1080 BaseSecurity::addUserPrivateKeyPEM(const Data& aor, const Data& cert)
1081 {
1082 addPrivateKeyPEM(UserPrivateKey, aor, cert, true);
1083 }
1084 void
1085 BaseSecurity::addUserPrivateKeyDER(const Data& aor, const Data& cert)
1086 {
1087 addPrivateKeyDER(UserPrivateKey, aor, cert, true);
1088 }
1089 bool
1090 BaseSecurity::hasUserPrivateKey(const Data& aor) const
1091 {
1092 return hasPrivateKey(UserPrivateKey, aor, true);
1093 }
1094 bool
1095 BaseSecurity::removeUserPrivateKey(const Data& aor)
1096 {
1097 return removePrivateKey(UserPrivateKey, aor, true);
1098 }
1099 Data
1100 BaseSecurity::getUserPrivateKeyPEM(const Data& aor) const
1101 {
1102 return getPrivateKeyPEM(UserPrivateKey, aor, true);
1103 }
1104 Data
1105 BaseSecurity::getUserPrivateKeyDER(const Data& aor) const
1106 {
1107 return getPrivateKeyDER(UserPrivateKey, aor, true);
1108 }
1109
1110 void
1111 BaseSecurity::generateUserCert (const Data& aor, const Data& passPhrase)
1112 {
1113 assert(0);
1114 }
1115
1116 MultipartSignedContents*
1117 BaseSecurity::sign(const Data& senderAor, Contents* contents)
1118 {
1119 DebugLog( << "Doing multipartSign" );
1120 assert( contents );
1121
1122 // form the multipart
1123 MultipartSignedContents* multi = new MultipartSignedContents;
1124 multi->header(h_ContentType).param( p_micalg ) = "sha1";
1125 multi->header(h_ContentType).param( p_protocol ) = "application/pkcs7-signature";
1126
1127 // add the main body to it
1128 Contents* body = contents->clone();
1129
1130 #if 0
1131 // this need to be set in body before it is passed in
1132 body->header(h_ContentTransferEncoding).value() = StringCategory(Data("binary"));
1133 #endif
1134 multi->parts().push_back( body );
1135
1136 // compute the signature
1137 int flags = 0;
1138 flags |= PKCS7_BINARY;
1139 flags |= PKCS7_DETACHED;
1140 #if 0 // TODO !cj!
1141 flags |= PKCS7_NOCERTS; // should remove
1142 flags |= PKCS7_NOATTR;
1143 flags |= PKCS7_NOSMIMECAP;
1144 #endif
1145
1146 Data bodyData;
1147 DataStream strm( bodyData );
1148 body->encodeHeaders( strm );
1149 body->encode( strm );
1150 strm.flush();
1151
1152 DebugLog( << "sign the data <" << bodyData << ">" );
1153 Security::dumpAsn("resip-sign-out-data",bodyData);
1154
1155 const char* p = bodyData.data();
1156 int s = bodyData.size();
1157 BIO* in=BIO_new_mem_buf( (void*)p,s);
1158 assert(in);
1159 DebugLog( << "ceated in BIO");
1160
1161 BIO* out = BIO_new(BIO_s_mem());
1162 assert(out);
1163 DebugLog( << "created out BIO" );
1164
1165 STACK_OF(X509)* chain = sk_X509_new_null();
1166 assert(chain);
1167
1168 DebugLog( << "checking" );
1169 if (mUserCerts.count(senderAor) == 0 ||
1170 mUserPrivateKeys.count(senderAor) == 0)
1171 {
1172 WarningLog (<< "Tried to sign with no cert or private key for " << senderAor);
1173 throw Exception("No cert or private key to sign with",__FILE__,__LINE__);
1174 }
1175
1176 X509* publicCert = mUserCerts[senderAor];
1177 EVP_PKEY* privateKey = mUserPrivateKeys[senderAor];
1178
1179 int i = X509_check_private_key(publicCert, privateKey);
1180 DebugLog( << "checked cert and key ret=" << i );
1181
1182 PKCS7* pkcs7 = PKCS7_sign( publicCert, privateKey, chain, in, flags);
1183 if ( !pkcs7 )
1184 {
1185 ErrLog( << "Error creating PKCS7 signature object" );
1186 return 0;
1187 }
1188 DebugLog( << "created PKCS7 signature object " );
1189
1190 i2d_PKCS7_bio(out,pkcs7);
1191 BIO_flush(out);
1192
1193 char* outBuf=0;
1194 long size = BIO_get_mem_data(out,&outBuf);
1195 assert( size > 0 );
1196
1197 Data outData(outBuf,size);
1198 Security::dumpAsn("resip-sign-out-sig",outData);
1199
1200 Pkcs7Contents* sigBody = new Pkcs7Contents( outData );
1201 assert( sigBody );
1202
1203 //sigBody->header(h_ContentType).type() = "application";
1204 //sigBody->header(h_ContentType).subType() = "pkcs7-signature";
1205 //sigBody->header(h_ContentType).param( "smime-type" ) = "signed-data";
1206 sigBody->header(h_ContentType).param( p_name ) = "smime.p7s";
1207 sigBody->header(h_ContentDisposition).param( p_handling ) = "required";
1208 sigBody->header(h_ContentDisposition).param( p_filename ) = "smime.p7s";
1209 sigBody->header(h_ContentDisposition).value() = "attachment" ;
1210 sigBody->header(h_ContentTransferEncoding).value() = "binary";
1211
1212 // add the signature to it
1213 multi->parts().push_back( sigBody );
1214 assert( multi->parts().size() == 2 );
1215
1216 return multi;
1217 }
1218
1219 Pkcs7Contents*
1220 BaseSecurity::encrypt(Contents* bodyIn, const Data& recipCertName )
1221 {
1222 assert( bodyIn );
1223
1224 int flags = 0 ;
1225 flags |= PKCS7_BINARY;
1226 #if 0 // TODO !cj!
1227 // will cause it not to send certs in the signature
1228 flags |= PKCS7_NOCERTS;
1229 #endif
1230
1231 Data bodyData;
1232 DataStream strm(bodyData);
1233 bodyIn->encodeHeaders(strm);
1234 bodyIn->encode( strm );
1235 strm.flush();
1236
1237 InfoLog( << "body data to encrypt is <" << bodyData.escaped() << ">" );
1238
1239 const char* p = bodyData.data();
1240 int s = bodyData.size();
1241
1242 BIO* in = BIO_new_mem_buf( (void*)p,s);
1243 assert(in);
1244 DebugLog( << "ceated in BIO");
1245
1246 BIO* out = BIO_new(BIO_s_mem());
1247 assert(out);
1248 DebugLog( << "created out BIO" );
1249
1250 InfoLog( << "target cert name is " << recipCertName );
1251 if (mUserCerts.count(recipCertName) == 0)
1252 {
1253 WarningLog (<< "Tried to encrypt with no cert or private key for " << recipCertName);
1254 throw Exception("No cert or private key to encrypt with",__FILE__,__LINE__);
1255 }
1256
1257 X509* cert = mUserCerts[recipCertName];
1258 assert(cert);
1259
1260 STACK_OF(X509) *certs = sk_X509_new_null();
1261 assert(certs);
1262 sk_X509_push(certs, cert);
1263
1264 // if you think you need to change the following few lines, please email fluffy
1265 // the value of OPENSSL_VERSION_NUMBER ( in opensslv.h ) and the signature of
1266 // PKCS_encrypt found ( in pkcs7.h ) and the OS you are using
1267 #if ( OPENSSL_VERSION_NUMBER > 0x009060ffL )
1268 const EVP_CIPHER* cipher = EVP_des_ede3_cbc();
1269 #else
1270 EVP_CIPHER* cipher = EVP_des_ede3_cbc();
1271 #endif
1272 //const EVP_CIPHER* cipher = EVP_aes_128_cbc();
1273 //const EVP_CIPHER* cipher = EVP_enc_null();
1274 assert( cipher );
1275
1276 PKCS7* pkcs7 = PKCS7_encrypt( certs, in, cipher, flags);
1277 if ( !pkcs7 )
1278 {
1279 ErrLog( << "Error creating PKCS7 encrypt object" );
1280 throw Exception("Can't encrypt",__FILE__,__LINE__);
1281 }
1282 DebugLog( << "created PKCS7 encrypt object " );
1283
1284 i2d_PKCS7_bio(out,pkcs7);
1285
1286 BIO_flush(out);
1287
1288 char* outBuf=0;
1289 long size = BIO_get_mem_data(out,&outBuf);
1290 assert( size > 0 );
1291
1292 Data outData(outBuf,size);
1293 assert( (long)outData.size() == size );
1294
1295 InfoLog( << Data("Encrypted body size is ") << outData.size() );
1296 InfoLog( << Data("Encrypted body is <") << outData.escaped() << ">" );
1297
1298 Security::dumpAsn("resip-encrpt-out",outData);
1299
1300 Pkcs7Contents* outBody = new Pkcs7Contents( outData );
1301 assert( outBody );
1302
1303 //outBody->header(h_ContentType).type() = "application";
1304 //outBody->header(h_ContentType).subType() = "pkcs7-mime";
1305 outBody->header(h_ContentType).param( p_smimeType ) = "enveloped-data";
1306 outBody->header(h_ContentType).param( p_name ) = "smime.p7m";
1307 outBody->header(h_ContentDisposition).param( p_handling ) = "required";
1308 outBody->header(h_ContentDisposition).param( p_filename ) = "smime.p7";
1309 outBody->header(h_ContentDisposition).value() = "attachment" ;
1310
1311 return outBody;
1312 }
1313
1314 Pkcs7Contents*
1315 BaseSecurity::signAndEncrypt( const Data& senderAor, Contents* body, const Data& recipCertName )
1316 {
1317 return 0;
1318 //return sign(senderAor, encrypt(body, recipCertName));
1319 }
1320
1321 Data
1322 BaseSecurity::computeIdentity( const Data& signerDomain, const Data& in ) const
1323 {
1324 DebugLog( << "Compute identity for " << in );
1325
1326 if (mDomainPrivateKeys.count(signerDomain) == 0)
1327 {
1328 ErrLog( << "No private key for " << signerDomain );
1329 throw Exception("Missing private key when computing identity",__FILE__,__LINE__);
1330 }
1331
1332 EVP_PKEY* pKey = mDomainPrivateKeys[signerDomain];
1333 assert( pKey );
1334
1335 assert( pKey->type == EVP_PKEY_RSA );
1336 RSA* rsa = EVP_PKEY_get1_RSA(pKey);
1337
1338 unsigned char result[4096];
1339 int resultSize = sizeof(result);
1340 assert( resultSize >= RSA_size(rsa) );
1341
1342 assert(SHA_DIGEST_LENGTH == 20);
1343 unsigned char hashRes[SHA_DIGEST_LENGTH];
1344 unsigned int hashResLen=SHA_DIGEST_LENGTH;
1345
1346 SHA_CTX sha;
1347 SHA1_Init( &sha );
1348 SHA1_Update(&sha, in.data() , in.size() );
1349 SHA1_Final( hashRes, &sha );
1350
1351 DebugLog( << "hash of string is 0x" << Data(hashRes,sizeof(hashRes)).hex() );
1352
1353 #if 1
1354 int r = RSA_sign(NID_sha1, hashRes, hashResLen,
1355 result, (unsigned int*)( &resultSize ),
1356 rsa);
1357 assert( r == 1 );
1358 #else
1359 resultSize = RSA_private_encrypt(hashResLen, hashRes,
1360 result, rsa, RSA_PKCS1_PADDING);
1361 if ( resultSize == -1 )
1362 {
1363 DebugLog( << "Problem doing RSA encrypt for identity");
1364 while (1)
1365 {
1366 const char* file;
1367 int line;
1368
1369 unsigned long code = ERR_get_error_line(&file,&line);
1370 if ( code == 0 )
1371 {
1372 break;
1373 }
1374
1375 char buf[256];
1376 ERR_error_string_n(code,buf,sizeof(buf));
1377 ErrLog( << buf );
1378 InfoLog( << "Error code = " << code << " file="<<file<<" line=" << line );
1379 }
1380
1381 return Data::Empty;
1382 }
1383 #endif
1384
1385 Data res(result,resultSize);
1386 DebugLog( << "rsa encrypt of hash is 0x"<< res.hex() );
1387
1388 Data enc = res.base64encode();
1389
1390 Security::dumpAsn("identity-in", in );
1391 Security::dumpAsn("identity-in-hash", Data(hashRes, hashResLen) );
1392 Security::dumpAsn("identity-in-rsa",res);
1393 Security::dumpAsn("identity-in-base64",enc);
1394
1395 return enc;
1396 }
1397
1398 bool
1399 BaseSecurity::checkIdentity( const Data& signerDomain, const Data& in, const Data& sigBase64 ) const
1400 {
1401 if (mDomainCerts.count(signerDomain) == 0)
1402 {
1403 ErrLog( << "No public key for " << signerDomain );
1404 throw Exception("Missing public key when verifying identity",__FILE__,__LINE__);
1405 }
1406 X509* cert = mDomainCerts[signerDomain];
1407
1408 DebugLog( << "Check identity for " << in );
1409 DebugLog( << " base64 data is " << sigBase64 );
1410
1411 Data sig = sigBase64.base64decode();
1412 DebugLog( << "decoded sig is 0x"<< sig.hex() );
1413
1414 assert(SHA_DIGEST_LENGTH == 20);
1415 unsigned char hashRes[SHA_DIGEST_LENGTH];
1416 unsigned int hashResLen=SHA_DIGEST_LENGTH;
1417
1418 SHA_CTX sha;
1419 SHA1_Init( &sha );
1420 SHA1_Update(&sha, in.data() , in.size() );
1421 SHA1_Final( hashRes, &sha );
1422 Data computedHash(hashRes, hashResLen);
1423
1424 DebugLog( << "hash of string is 0x" << Data(hashRes,sizeof(hashRes)).hex() );
1425
1426 EVP_PKEY* pKey = X509_get_pubkey( cert );
1427 assert( pKey );
1428
1429 assert( pKey->type == EVP_PKEY_RSA );
1430 RSA* rsa = EVP_PKEY_get1_RSA(pKey);
1431
1432 #if 1
1433 int ret = RSA_verify(NID_sha1, hashRes, hashResLen,
1434 (unsigned char*)sig.data(), sig.size(),
1435 rsa);
1436 #else
1437 unsigned char result[4096];
1438 int resultSize = sizeof(result);
1439 assert( resultSize >= RSA_size(rsa) );
1440
1441 resultSize = RSA_public_decrypt(sig.size(),(unsigned char*)sig.data(),
1442 result, rsa, RSA_PKCS1_PADDING );
1443 assert( resultSize != -1 );
1444 //assert( resultSize == SHA_DIGEST_LENGTH );
1445 Data recievedHash(result,resultSize);
1446 dumpAsn("identity-out-decrypt", recievedHash );
1447
1448 bool ret = ( computedHash == recievedHash );
1449 #endif
1450
1451 DebugLog( << "rsa verify result is " << ret );
1452
1453 dumpAsn("identity-out-msg", in );
1454 dumpAsn("identity-out-base64", sigBase64 );
1455 dumpAsn("identity-out-sig", sig );
1456 dumpAsn("identity-out-hash", computedHash );
1457
1458 return ret;
1459 }
1460
1461 void
1462 BaseSecurity::checkAndSetIdentity( const SipMessage& msg ) const
1463 {
1464 auto_ptr<SecurityAttributes> sec(new SecurityAttributes);
1465
1466 try
1467 {
1468 if (checkIdentity(msg.header(h_From).uri().host(),
1469 msg.getCanonicalIdentityString(),
1470 msg.header(h_Identity).value()))
1471 {
1472 sec->setIdentity(msg.header(h_From).uri().getAor());
1473 sec->setIdentityStrength(SecurityAttributes::Identity);
1474 }
1475 else
1476 {
1477 sec->setIdentity(msg.header(h_From).uri().getAor());
1478 sec->setIdentityStrength(SecurityAttributes::FailedIdentity);
1479 }
1480 }
1481 catch (BaseException&)
1482 {
1483 sec->setIdentity(msg.header(h_From).uri().getAor());
1484 sec->setIdentityStrength(SecurityAttributes::FailedIdentity);
1485 }
1486 msg.setSecurityAttributes(sec);
1487 }
1488
1489 Contents*
1490 BaseSecurity::decrypt( const Data& decryptorAor, Pkcs7Contents* contents)
1491 {
1492 int flags=0;
1493 flags |= PKCS7_BINARY;
1494
1495 // for now, assume that this is only a singed message
1496 assert( contents );
1497
1498 Data text = contents->getBodyData();
1499 DebugLog( << "uncode body = <" << text.escaped() << ">" );
1500 DebugLog( << "uncode body size = " << text.size() );
1501
1502 Security::dumpAsn("resip-asn-decrypt", text );
1503
1504 BIO* in = BIO_new_mem_buf( (void*)text.c_str(),text.size());
1505 assert(in);
1506 InfoLog( << "ceated in BIO");
1507
1508 BIO* out;
1509 out = BIO_new(BIO_s_mem());
1510 assert(out);
1511 InfoLog( << "created out BIO" );
1512
1513 PKCS7* pkcs7 = d2i_PKCS7_bio(in, 0);
1514 if ( !pkcs7 )
1515 {
1516 ErrLog( << "Problems doing decode of PKCS7 object" );
1517
1518 while (1)
1519 {
1520 const char* file;
1521 int line;
1522
1523 unsigned long code = ERR_get_error_line(&file,&line);
1524 if ( code == 0 )
1525 {
1526 break;
1527 }
1528
1529 char buf[256];
1530 ERR_error_string_n(code,buf,sizeof(buf));
1531 ErrLog( << buf );
1532 InfoLog( << "Error code = " << code << " file=" << file << " line=" << line );
1533 }
1534
1535 return 0;
1536 }
1537 BIO_flush(in);
1538
1539 int type=OBJ_obj2nid(pkcs7->type);
1540 switch (type)
1541 {
1542 case NID_pkcs7_signed:
1543 InfoLog( << "data is pkcs7 signed" );
1544 break;
1545 case NID_pkcs7_signedAndEnveloped:
1546 InfoLog( << "data is pkcs7 signed and enveloped" );
1547 break;
1548 case NID_pkcs7_enveloped:
1549 InfoLog( << "data is pkcs7 enveloped" );
1550 break;
1551 case NID_pkcs7_data:
1552 InfoLog( << "data i pkcs7 data" );
1553 break;
1554 case NID_pkcs7_encrypted:
1555 InfoLog( << "data is pkcs7 encrypted " );
1556 break;
1557 case NID_pkcs7_digest:
1558 InfoLog( << "data is pkcs7 digest" );
1559 break;
1560 default:
1561 InfoLog( << "Unkown pkcs7 type" );
1562 break;
1563 }
1564
1565 STACK_OF(X509)* certs = sk_X509_new_null();
1566 assert( certs );
1567
1568 // flags |= PKCS7_NOVERIFY;
1569
1570 assert( mRootCerts );
1571
1572 switch (type)
1573 {
1574 case NID_pkcs7_signedAndEnveloped:
1575 {
1576 throw Exception("Signed and enveloped is not supported", __FILE__, __LINE__);
1577 }
1578 break;
1579
1580 case NID_pkcs7_enveloped:
1581 {
1582 if (mUserPrivateKeys.count(decryptorAor) == 0)
1583 {
1584 InfoLog( << "Don't have a private key for " << decryptorAor << " for PKCS7_decrypt" );
1585 throw Exception("Missing private key", __FILE__, __LINE__);
1586 }
1587 else if (mUserCerts.count(decryptorAor) == 0)
1588 {
1589 InfoLog( << "Don't have a public cert for " << decryptorAor << " for PKCS7_decrypt" );
1590 throw Exception("Missing cert", __FILE__, __LINE__);
1591 }
1592
1593 EVP_PKEY* privateKey = mUserPrivateKeys[decryptorAor];
1594 X509* publicCert = mUserCerts[decryptorAor];
1595
1596 if ( PKCS7_decrypt(pkcs7, privateKey, publicCert, out, flags ) != 1 )
1597 {
1598 ErrLog( << "Problems doing PKCS7_decrypt" );
1599 while (1)
1600 {
1601 const char* file;
1602 int line;
1603
1604 unsigned long code = ERR_get_error_line(&file,&line);
1605 if ( code == 0 )
1606 {
1607 break;
1608 }
1609
1610 char buf[256];
1611 ERR_error_string_n(code,buf,sizeof(buf));
1612 ErrLog( << buf );
1613 InfoLog( << "Error code = " << code << " file=" << file << " line=" << line );
1614 }
1615
1616 return 0;
1617 }
1618 }
1619 break;
1620
1621 default:
1622 ErrLog(<< "Got PKCS7 data that could not be handled type=" << type );
1623 throw Exception("Unsupported PKCS7 data type", __FILE__, __LINE__);
1624 }
1625
1626 BIO_flush(out);
1627 char* outBuf=0;
1628 long size = BIO_get_mem_data(out,&outBuf);
1629 assert( size >= 0 );
1630
1631 Data outData(outBuf,size);
1632 DebugLog( << "uncoded body is <" << outData.escaped() << ">" );
1633
1634 // parse out the header information and form new body.
1635 // !jf! this is a really crappy parser - shoudl do proper mime stuff
1636 ParseBuffer pb( outData.data(), outData.size() );
1637
1638 const char* headerStart = pb.position();
1639
1640 // pull out contents type only
1641 pb.skipToChars("Content-Type");
1642 pb.assertNotEof();
1643
1644 pb.skipToChar(Symbols::COLON[0]);
1645 pb.skipChar();
1646 pb.assertNotEof();
1647
1648 pb.skipWhitespace();
1649 const char* typeStart = pb.position();
1650 pb.assertNotEof();
1651
1652 // determine contents-type header buffer
1653 pb.skipToTermCRLF();
1654 pb.assertNotEof();
1655
1656 ParseBuffer subPb(typeStart, pb.position() - typeStart);
1657 Mime contentType;
1658 contentType.parse(subPb);
1659
1660 pb.assertNotEof();
1661
1662 // determine body start
1663 pb.reset(typeStart);
1664 const char* bodyStart = pb.skipToChars(Symbols::CRLFCRLF);
1665 pb.assertNotEof();
1666 bodyStart += 4;
1667
1668 // determine contents body buffer
1669 pb.skipToEnd();
1670 Data tmp;
1671 pb.data(tmp, bodyStart);
1672 // create contents against body
1673 Contents* ret = Contents::createContents(contentType, tmp);
1674 // pre-parse headers
1675 ParseBuffer headersPb(headerStart, bodyStart-4-headerStart);
1676 ret->preParseHeaders(headersPb);
1677
1678 DebugLog( << "Got body data of " << ret->getBodyData() );
1679
1680 return ret;
1681 }
1682
1683 Contents*
1684 BaseSecurity::checkSignature(MultipartSignedContents* multi,
1685 Data* signedBy,
1686 SignatureStatus* sigStat )
1687 {
1688 if ( multi->parts().size() != 2 )
1689 {
1690 ErrLog(<< "Trying to decode a message with wrong number of contents " << multi->parts().size());
1691 throw Exception("Invalid contents passed to checkSignature", __FILE__, __LINE__);
1692 }
1693
1694 list<Contents*>::const_iterator i = multi->parts().begin();
1695 Contents* first = *i;
1696 ++i;
1697 assert( i != multi->parts().end() );
1698 Contents* second = *i;
1699 Pkcs7SignedContents* sig = dynamic_cast<Pkcs7SignedContents*>( second );
1700
1701 if ( !sig )
1702 {
1703 ErrLog( << "Don't know how to deal with signature type " );
1704 throw Exception("Invalid contents passed to checkSignature", __FILE__, __LINE__);
1705 }
1706
1707 int flags=0;
1708 flags |= PKCS7_BINARY;
1709
1710 assert( second );
1711 assert( first );
1712
1713 //CerrLog( << "message to sign is " << *first );
1714
1715 Data bodyData;
1716 DataStream strm( bodyData );
1717 first->encodeHeaders( strm );
1718 first->encode( strm );
1719 strm.flush();
1720 //CerrLog( << "encoded version to sign is " << bodyData );
1721
1722 // Data textData = first->getBodyData();
1723 Data textData = bodyData;
1724 Data sigData = sig->getBodyData();
1725
1726 Security::dumpAsn( "resip-asn-uncode-signed-text", textData );
1727 Security::dumpAsn( "resip-asn-uncode-signed-sig", sigData );
1728
1729 BIO* in = BIO_new_mem_buf( (void*)sigData.data(),sigData.size());
1730 assert(in);
1731 InfoLog( << "ceated in BIO");
1732
1733 BIO* out = BIO_new(BIO_s_mem());
1734 assert(out);
1735 InfoLog( << "created out BIO" );
1736
1737 DebugLog( << "verify <" << textData.escaped() << ">" );
1738 DebugLog( << "signature <" << sigData.escaped() << ">" );
1739
1740 BIO* pkcs7Bio = BIO_new_mem_buf( (void*) textData.data(),textData.size());
1741 assert(pkcs7Bio);
1742 InfoLog( << "ceated pkcs BIO");
1743
1744 PKCS7* pkcs7 = d2i_PKCS7_bio(in, 0);
1745 if ( !pkcs7 )
1746 {
1747 ErrLog( << "Problems doing decode of PKCS7 object <"
1748 << sigData.escaped() << ">" );
1749
1750 while (1)
1751 {
1752 const char* file;
1753 int line;
1754
1755 unsigned long code = ERR_get_error_line(&file,&line);
1756 if ( code == 0 )
1757 {
1758 break;
1759 }
1760
1761 char buf[256];
1762 ERR_error_string_n(code,buf,sizeof(buf));
1763 ErrLog( << buf );
1764 InfoLog( <<"Error code = "<< code <<" file=" << file << " line=" << line );
1765 }
1766
1767 return first;
1768 }
1769 BIO_flush(in);
1770
1771 int type=OBJ_obj2nid(pkcs7->type);
1772 switch (type)
1773 {
1774 case NID_pkcs7_signed:
1775 InfoLog( << "data is pkcs7 signed" );
1776 break;
1777 case NID_pkcs7_signedAndEnveloped:
1778 InfoLog( << "data is pkcs7 signed and enveloped" );
1779 break;
1780 case NID_pkcs7_enveloped:
1781 InfoLog( << "data is pkcs7 enveloped" );
1782 break;
1783 case NID_pkcs7_data:
1784 InfoLog( << "data is pkcs7 data" );
1785 break;
1786 case NID_pkcs7_encrypted:
1787 InfoLog( << "data is pkcs7 encrypted " );
1788 break;
1789 case NID_pkcs7_digest:
1790 InfoLog( << "data is pkcs7 digest" );
1791 break;
1792 default:
1793 InfoLog( << "Unkown pkcs7 type" );
1794 break;
1795 }
1796
1797 STACK_OF(X509)* certs = 0;
1798 certs = sk_X509_new_null();
1799 assert( certs );
1800
1801 if ( *signedBy == Data::Empty )
1802 {
1803 assert(0);
1804 // need to add back in code that adds all certs when sender unkonwn
1805 }
1806 else
1807 {
1808 if (mUserCerts.count( *signedBy))
1809 {
1810 X509* cert = mUserCerts[ *signedBy ];
1811 assert(cert);
1812 sk_X509_push(certs, cert);
1813 }
1814 }
1815
1816 //flags |= PKCS7_NOINTERN;
1817 //flags |= PKCS7_NOVERIFY;
1818 //flags |= PKCS7_NOSIGS;
1819
1820 STACK_OF(X509)* signers = PKCS7_get0_signers(pkcs7,certs, flags );
1821 if ( signers )
1822 {
1823 for (int i=0; i<sk_X509_num(signers); i++)
1824 {
1825 X509* x = sk_X509_value(signers,i);
1826 InfoLog(<< "Got a signer <" << i << ">" );
1827
1828 GENERAL_NAMES* gens=0;
1829 gens = (GENERAL_NAMES*)X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);
1830
1831 for(i = 0; i < sk_GENERAL_NAME_num(gens); i++)
1832 {
1833 GENERAL_NAME* gen = sk_GENERAL_NAME_value(gens, i);
1834 if(gen->type == GEN_URI)
1835 {
1836 ASN1_IA5STRING* uri = gen->d.uniformResourceIdentifier;
1837 int l = uri->length;
1838 unsigned char* dat = uri->data;
1839 Data name(dat,l);
1840 InfoLog(<< "subjectAltName of signing cert contains <" << name << ">" );
1841
1842 try
1843 {
1844 Uri n(name);
1845 if ( n.scheme() == "sip" )
1846 {
1847 *signedBy = name;
1848 InfoLog(<< "choose <" << name << "> signature" );
1849 }
1850 }
1851 catch (ParseBuffer::Exception& e)
1852 {
1853 }
1854 }
1855 }
1856
1857 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
1858 }
1859 }
1860 else
1861 {
1862 *sigStat = SignatureIsBad;
1863 InfoLog(<< "No valid signers of this messages" );
1864 return first;
1865 }
1866
1867 #if 0
1868 // this is debugging information to get the serial number of the signed
1869 // information
1870 STACK_OF(PKCS7_SIGNER_INFO) *sinfos;
1871 PKCS7_SIGNER_INFO *si;
1872 PKCS7_ISSUER_AND_SERIAL *ias;
1873 ASN1_INTEGER* asnSerial;
1874 long longSerial;
1875 X509_NAME* name;
1876
1877 sinfos = PKCS7_get_signer_info(pkcs7);
1878 if ( sinfos )
1879 {
1880 int num = sk_PKCS7_SIGNER_INFO_num(sinfos);
1881 for ( int i=0; i<num; i++ )
1882 {
1883 si = sk_PKCS7_SIGNER_INFO_value (sinfos, i) ;
1884 ias = si->issuer_and_serial;
1885 name = ias->issuer;
1886 asnSerial = ias->serial;
1887 longSerial = ASN1_INTEGER_get( (ASN1_INTEGER*)asnSerial );
1888 InfoLog(<<"Signed with serial " << hex << longSerial );
1889 }
1890 }
1891 #endif
1892
1893 assert( mRootCerts );
1894
1895 switch (type)
1896 {
1897 case NID_pkcs7_signed:
1898 {
1899 if ( PKCS7_verify(pkcs7, certs, mRootCerts, pkcs7Bio, out, flags ) != 1 )
1900 {
1901 ErrLog( << "Problems doing PKCS7_verify" );
1902
1903 if ( sigStat )
1904 {
1905 *sigStat = SignatureIsBad;
1906 }
1907
1908 while (1)
1909 {
1910 const char* file;
1911 int line;
1912
1913 unsigned long code = ERR_get_error_line(&file,&line);
1914 if ( code == 0 )
1915 {
1916 break;
1917 }
1918
1919 char buf[256];
1920 ERR_error_string_n(code,buf,sizeof(buf));
1921 ErrLog( << buf );
1922 InfoLog( << "Error code = " << code << " file=" << file << " line=" << line );
1923 }
1924
1925 return first;
1926 }
1927 if ( sigStat )
1928 {
1929 if ( flags & PKCS7_NOVERIFY )
1930 {
1931 DebugLog( << "Signature is notTrusted" );
1932 *sigStat = SignatureNotTrusted;
1933 }
1934 else
1935 {
1936 if (false) // !jf! TODO look for this cert in store
1937 {
1938 DebugLog( << "Signature is trusted" );
1939 *sigStat = SignatureTrusted;
1940 }
1941 else
1942 {
1943 DebugLog( << "Signature is caTrusted" );
1944 *sigStat = SignatureCATrusted;
1945 }
1946 }
1947 }
1948 }
1949 break;
1950
1951 default:
1952 ErrLog(<< "Got PKCS7 data that could not be handled type=" << type );
1953 return 0;
1954 }
1955
1956 BIO_flush(out);
1957 char* outBuf=0;
1958 long size = BIO_get_mem_data(out,&outBuf);
1959 assert( size >= 0 );
1960
1961 Data outData(outBuf,size);
1962 DebugLog( << "uncoded body is <" << outData.escaped() << ">" );
1963
1964 return first;
1965 }
1966
1967 SSL_CTX*
1968 BaseSecurity::getTlsCtx ()
1969 {
1970 if (mTlsCtx == 0)
1971 {
1972 mTlsCtx = SSL_CTX_new( TLSv1_method() );
1973 assert(mTlsCtx);
1974
1975 // make sure we have root certs
1976 assert(mRootCerts);
1977 configSslCtx(mTlsCtx, mRootCerts);
1978 }
1979
1980 return mTlsCtx;
1981 }
1982 SSL_CTX*
1983 BaseSecurity::getSslCtx ()
1984 {
1985 if (mSslCtx == 0)
1986 {
1987 mSslCtx = SSL_CTX_new( SSLv23_method() );
1988 assert(mSslCtx);
1989
1990 // make sure we have root certs
1991 assert(mRootCerts);
1992 configSslCtx(mSslCtx, mRootCerts);
1993 }
1994
1995 return mSslCtx;
1996 }
1997
1998 void
1999 BaseSecurity::dumpAsn( char* name, Data data)
2000 {
2001 #if 0 // !CJ! TODO turn off
2002 assert(name);
2003
2004 if (true) // dump asn.1 stuff to debug file
2005 {
2006 ofstream strm(name, std::ios_base::trunc);
2007 if ( !strm )
2008 {
2009 ErrLog( <<"Could not write to " << name );
2010 }
2011 else
2012 {
2013 strm.write( data.data() , data.size() );
2014 }
2015 strm.flush();
2016 }
2017 #endif
2018 }
2019
2020 #endif
2021
2022 /* ====================================================================
2023 * The Vovida Software License, Version 1.0
2024 *
2025 * Copyright (c) 2000 Vovida Networks, Inc. All rights reserved.
2026 *
2027 * Redistribution and use in source and binary forms, with or without
2028 * modification, are permitted provided that the following conditions
2029 * are met:
2030 *
2031 * 1. Redistributions of source code must retain the above copyright
2032 * notice, this list of conditions and the following disclaimer.
2033 *
2034 * 2. Redistributions in binary form must reproduce the above copyright
2035 * notice, this list of conditions and the following disclaimer in
2036 * the documentation and/or other materials provided with the
2037 * distribution.
2038 *
2039 * 3. The names "VOCAL", "Vovida Open Communication Application Library",
2040 * and "Vovida Open Communication Application Library (VOCAL)" must
2041 * not be used to endorse or promote products derived from this
2042 * software without prior written permission. For written
2043 * permission, please contact vocal@vovida.org.
2044 *
2045 * 4. Products derived from this software may not be called "VOCAL", nor
2046 * may "VOCAL" appear in their name, without prior written
2047 * permission of Vovida Networks, Inc.
2048 *
2049 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED
2050 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
2051 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE AND
2052 * NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL VOVIDA
2053 * NETWORKS, INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT DAMAGES
2054 * IN EXCESS OF $1,000, NOR FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
2055 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
2056 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
2057 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
2058 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
2059 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
2060 * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
2061 * DAMAGE.
2062 *
2063 * ====================================================================
2064 *
2065 * This software consists of voluntary contributions made by Vovida
2066 * Networks, Inc. and many individuals on behalf of Vovida Networks,
2067 * Inc. For more information on Vovida Networks, Inc., please see
2068 * <http://www.vovida.org/>.
2069 *
2070 */

webmaster AT resiprocate DOT org
ViewVC Help
Powered by ViewVC 1.1.27