⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 security.cxx

📁 一个著名的SIP协议栈
💻 CXX
📖 第 1 页 / 共 5 页
字号:
   sk_X509_free(certs);

   // parse out the header information and form new body.
   // TODO !jf! this is a really crappy parser - shoudl do proper mime stuff 
   ParseBuffer pb(buffer, len);

   const char* headerStart = pb.position();

   // pull out contents type only
   pb.skipToChars("Content-Type");
   pb.assertNotEof();

   pb.skipToChar(Symbols::COLON[0]);
   pb.skipChar();
   pb.assertNotEof();

   pb.skipWhitespace();
   const char* typeStart = pb.position();
   pb.assertNotEof();

   // determine contents-type header buffer
   pb.skipToTermCRLF();
   pb.assertNotEof();

   ParseBuffer subPb(typeStart, pb.position() - typeStart);
   Mime contentType;
   contentType.parse(subPb);

   pb.assertNotEof();

   // determine body start
   pb.reset(typeStart);
   const char* bodyStart = pb.skipToChars(Symbols::CRLFCRLF);
   pb.assertNotEof();
   bodyStart += 4;

   // determine contents body buffer
   pb.skipToEnd();
   Data tmp;
   pb.data(tmp, bodyStart);
   // create contents against body
   Contents* ret = Contents::createContents(contentType, tmp);
   ret->addBuffer(buffer);
   
   // pre-parse headers
   ParseBuffer headersPb(headerStart, bodyStart-4-headerStart);
   ret->preParseHeaders(headersPb);

   InfoLog( << "Got body data of " << ret->getBodyData() );

   return ret;
}





Contents*
BaseSecurity::checkSignature(MultipartSignedContents* multi,
                             Data* signedBy,
                             SignatureStatus* sigStat )
{
   if ( multi->parts().size() != 2 )
   {
      ErrLog(<< "Trying to decode a message with wrong number of contents " << multi->parts().size());
      throw Exception("Invalid contents passed to checkSignature", __FILE__, __LINE__);
   }

   MultipartSignedContents::Parts::const_iterator it = multi->parts().begin();
   Contents* first = *it;
   ++it;
   assert( it != multi->parts().end() );
   Contents* second = *it;

   assert( second );
   assert( first );

   InfoLog( << "message to signature-check is " << *first );

   Pkcs7SignedContents* sig = dynamic_cast<Pkcs7SignedContents*>( second );
   if ( !sig )
   {
      ErrLog( << "Don't know how to deal with signature type " );
      //throw Exception("Invalid contents passed to checkSignature", __FILE__,
      //__LINE__);
      return first;
   }
   Data sigData = sig->getBodyData();

   Data textData;
   DataStream strm( textData );
   first->encodeHeaders( strm );
   first->encode( strm );
   strm.flush();

   InfoLog( << "text <"    << textData.escaped() << ">" );
   InfoLog( << "signature <" << sigData.escaped() << ">" );

   static char RESIP_ASN_UNCODE_SIGNED_TEXT[] = "resip-asn-uncode-signed-text";
   static char RESIP_ASN_UNCODE_SIGNED_SIG[] = "resip-asn-uncode-signed-sig";

   Security::dumpAsn( RESIP_ASN_UNCODE_SIGNED_TEXT, textData );
   Security::dumpAsn( RESIP_ASN_UNCODE_SIGNED_SIG, sigData );

   BIO* in = BIO_new_mem_buf( (void*)sigData.data(),sigData.size());
   assert(in);
   InfoLog( << "created in BIO");

   BIO* out = BIO_new(BIO_s_mem());
   assert(out);
   InfoLog( << "created out BIO" );

   BIO* pkcs7Bio = BIO_new_mem_buf( (void*) textData.data(),textData.size());
   assert(pkcs7Bio);
   InfoLog( << "created pkcs7 BIO");

   PKCS7* pkcs7 = d2i_PKCS7_bio(in, 0);
   if ( !pkcs7 )
   {
      ErrLog( << "Problems doing decode of PKCS7 object <"
              << sigData.escaped() << ">" );

      while (1)
      {
         const char* file;
         int line;

         unsigned long code = ERR_get_error_line(&file,&line);
         if ( code == 0 )
         {
            break;
         }

         char buf[256];
         ERR_error_string_n(code,buf,sizeof(buf));
         ErrLog( << buf  );
         InfoLog( <<"Error code = "<< code <<" file=" << file << " line=" << line );
      }
      BIO_free(in);
      BIO_free(out);
      BIO_free(pkcs7Bio);

      return first;
   }
   BIO_flush(in);

   int type=OBJ_obj2nid(pkcs7->type);
   switch (type)
   {
      case NID_pkcs7_signed:
         InfoLog( << "data is pkcs7 signed" );
         break;
      case NID_pkcs7_signedAndEnveloped:
         InfoLog( << "data is pkcs7 signed and enveloped" );
         break;
      case NID_pkcs7_enveloped:
         InfoLog( << "data is pkcs7 enveloped" );
         break;
      case NID_pkcs7_data:
         InfoLog( << "data is pkcs7 data" );
         break;
      case NID_pkcs7_encrypted:
         InfoLog( << "data is pkcs7 encrypted " );
         break;
      case NID_pkcs7_digest:
         InfoLog( << "data is pkcs7 digest" );
         break;
      default:
         InfoLog( << "Unknown pkcs7 type" );
         break;
   }

   STACK_OF(X509)* certs = 0;
   certs = sk_X509_new_null();
   assert( certs );

   if ( *signedBy == Data::Empty )
   {   
       //add all the certificates from mUserCerts stack to 'certs' stack  
       for(X509Map::iterator it = mUserCerts.begin(); it != mUserCerts.end(); it++)
       {
           assert(it->second);
           sk_X509_push(certs, it->second);
       }
   }
   else
   {
      if (mUserCerts.count( *signedBy ))
      {
         InfoLog( <<"Adding cert from " <<  *signedBy << " to check sig" );
         X509* cert = mUserCerts[ *signedBy ];
         assert(cert);
         sk_X509_push(certs, cert);
      }
   }

   int flags = 0;
   flags |= PKCS7_NOINTERN;

   // matches on certificate issuer and serial number - they must be unique
   STACK_OF(X509)* signers = PKCS7_get0_signers(pkcs7, certs, flags);
   if ( signers )
   {

      DebugLog( << "Found " << sk_X509_num(signers) << " signers." );
      for (int i=0; i<sk_X509_num(signers); i++)
      {
         X509* x = sk_X509_value(signers, i);
         InfoLog(<< "Got a signer <" << i << "> : " << getCertName(x) );

         GENERAL_NAMES* gens = 0;
         gens = (GENERAL_NAMES*)X509_get_ext_d2i(x, NID_subject_alt_name, NULL, NULL);

         for (int j = 0; j < sk_GENERAL_NAME_num(gens); j++)
         {
            GENERAL_NAME* gen = sk_GENERAL_NAME_value(gens, j);
            if (gen->type == GEN_URI)
            {
               ASN1_IA5STRING* uri = gen->d.uniformResourceIdentifier;
               Data name(uri->data, uri->length);
               InfoLog(<< "subjectAltName of signing cert contains <" << name << ">" );
               try
               {
                  Uri n(name);
                  if ( n.scheme() == "sip" )
                  {
                     *signedBy = name;
                     InfoLog(<< "choose <" << name << "> signature" );
                 }
               }
               catch (...)
               {
               }
            }
         }

         sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
      }
   }
   else
   {
      BIO_free(in);
      BIO_free(out);
      BIO_free(pkcs7Bio);
      sk_X509_free(certs);
      *sigStat = SignatureIsBad;
      InfoLog(<< "No valid signers of this messages" );
      return first;
   }

#if 0
   // this is debugging information to get the serial number of the signed
   // information
   STACK_OF(PKCS7_SIGNER_INFO) *sinfos;
   PKCS7_SIGNER_INFO *si;
   PKCS7_ISSUER_AND_SERIAL *ias;
   ASN1_INTEGER* asnSerial;
   long longSerial;
   X509_NAME* name;

   sinfos = PKCS7_get_signer_info(pkcs7);
   if ( sinfos  )
   {
      int num = sk_PKCS7_SIGNER_INFO_num(sinfos);
      for ( int i=0; i<num; i++ )
      {
         si = sk_PKCS7_SIGNER_INFO_value (sinfos, i) ;
         ias = si->issuer_and_serial;
         name = ias->issuer;
         asnSerial = ias->serial;
         longSerial = ASN1_INTEGER_get( (ASN1_INTEGER*)asnSerial );
         InfoLog( << "Signed with serial " << hex << longSerial );
         InfoLog( << "Name " << name );
      }
   }
#endif

   assert( mRootTlsCerts );

   switch (type)
   {
      case NID_pkcs7_signed:
      {
         int flags = 0;

         if (isSelfSigned(sk_X509_value(signers,0)))
         {
            flags |= PKCS7_NOVERIFY;
         }

         if ( PKCS7_verify(pkcs7, certs, mRootTlsCerts, pkcs7Bio, out, flags ) != 1 )
         {
            ErrLog( << "Problems doing PKCS7_verify" );

            if ( sigStat )
            {
               *sigStat = SignatureIsBad;
            }

            while (1)
            {
               const char* file;
               int line;

               unsigned long code = ERR_get_error_line(&file,&line);
               if ( code == 0 )
               {
                  break;
               }

               char buf[256];
               ERR_error_string_n(code,buf,sizeof(buf));
               ErrLog( << buf  );
               InfoLog( << "Error code = " << code << " file=" << file << " line=" << line );
            }
            BIO_free(in);
            BIO_free(out);
            BIO_free(pkcs7Bio);
            sk_X509_free(certs);
            return first;
         }
         if ( sigStat )
         {
            if ( (flags & PKCS7_NOVERIFY) )
            {
               if (isSelfSigned(sk_X509_value(signers,0)))
               {
                  DebugLog( << "Signature is selfSigned");
                  *sigStat = SignatureSelfSigned;
               }
               else
               {
                  DebugLog( << "Signature is notTrusted" );
                  *sigStat = SignatureNotTrusted;
               }
            }
            else
            {
               if (false) // !jf! TODO look for this cert in store
               {
                  DebugLog( << "Signature is trusted" );
                  *sigStat = SignatureTrusted;
               }
               else
               {
                  DebugLog( << "Signature is caTrusted" );
                  *sigStat = SignatureCATrusted;
               }
            }
         }
      }
      break;

      default:
         BIO_free(in);
         BIO_free(out);
         BIO_free(pkcs7Bio);
         sk_X509_free(certs);
         ErrLog(<< "Got PKCS7 data that could not be handled type=" << type );
         return 0;
   }

   BIO_flush(out);
   char* outBuf=0;
   long size = BIO_get_mem_data(out,&outBuf);
   assert( size >= 0 );

   Data outData(outBuf,size);
   DebugLog( << "uncoded body is <" << outData.escaped() << ">" );

   BIO_free(in);
   BIO_free(out);
   BIO_free(pkcs7Bio);
   sk_X509_free(certs);
   return first;
}


SSL_CTX*
BaseSecurity::getTlsCtx ()
{
   assert(mTlsCtx);
   return   mTlsCtx;
}


SSL_CTX*
BaseSecurity::getSslCtx ()
{
   assert(mSslCtx);
   return   mSslCtx;
}

Data 
BaseSecurity::getCertName(X509 *cert)
{
    X509_NAME *subj;
    int       extcount;

    assert(cert);

    if ((extcount = X509_get_ext_count(cert)) > 0)
    {
        for (int i = 0;  i < extcount;  i++)
        {
            char              *extstr;
            X509_EXTENSION    *ext;
 
            ext = X509_get_ext(cert, i);
            extstr = (char*) OBJ_nid2sn(OBJ_obj2nid(X509_EXTENSION_get_object(ext)));
 
            if (!strcmp(extstr, "subjectAltName"))
            {
                int                  j;

#if (OPENSSL_VERSION_NUMBER < 0x0090800fL )
                unsigned char *data;
#else
                unsigned const char  *data;
#endif

                STACK_OF(CONF_VALUE) *val;
                CONF_VALUE           *nval;
                X509V3_EXT_METHOD    *meth;
                void                 *ext_str = NULL;
 
                if (!(meth = X509V3_EXT_get(ext)))
                    break;
                data = ext->value->data;

#if (OPENSSL_VERSION_NUMBER > 0x00907000L)
                if (meth->it)
                  ext_str = ASN1_item_d2i(NULL, &data, ext->value->length,
                                          ASN1_ITEM_ptr(meth->it));
                else
                  ext_str = meth->d2i(NULL, &data, ext->value->length);
#else
                ext_str = meth->d2i(NULL, &data, ext->value->length);
#endif
                val = meth->i2v(meth, ext_str, NULL);
                for (j = 0;  j < sk_CONF_VALUE_num(val);  j++)
                {
                    nval = sk_CONF_VALUE_value(val, j);
                    if (!strcmp(nval->name, "DNS"))
                    {
                        //retrieve name, from nval->value                        
                        return Data(nval->value);
                    }
                }
            }
        }
    }
 
    char cname[256];
    memset(cname, 0, sizeof cname);

    if ((subj = X509_get_subject_name(cert)) &&
        X509_NAME_get_text_by_NID(subj, NID_commonName, cname, sizeof(cname)-1) > 0)
    {        
        return Data(cname);
    }

    ErrLog(<< "This certificate doesn't have neither subjectAltName nor commonName");
    return Data::Empty;
}
/**
   Matchtes subjectAltName and cnames 
   @todo    looks incomplete, make better
*/
static int 
matchHostName(char *certName, const char *domainName)
{
   const char *dot;
   dot = strchr(domainName, '.');
   if (dot == NULL)
   {
      char *pnt = strchr(certName, '.');
      /

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -