📄 security.cxx
字号:
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 (ParseException& e) { ErrLog(<<"Caught exception: "<< e); } } } 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, '.'); /* hostname is not fully-qualified; unqualify the certName. */ if (pnt != NULL) { *pnt = '\0'; } } else { if (strncmp(certName, "*.", 2) == 0) { domainName = dot + 1; certName += 2; } } return !strcasecmp(certName, domainName);}bool BaseSecurity::compareCertName(X509 *cert, const Data& domainName){ assert(cert); Data certName = getCertName(cert); if(Data::Empty == certName) { InfoLog (<< "No cert name to match against " << domainName); return false; } DebugLog (<< "Matching " << certName << " cert against " << domainName); bool isMatching = matchHostName((char*)certName.c_str(), domainName.c_str()) ? true : false; return isMatching;}boolBaseSecurity::isSelfSigned(X509 *cert){ int iRet = X509_NAME_cmp(cert->cert_info->issuer, cert->cert_info->subject); return (iRet == 0);}voidBaseSecurity::dumpAsn( char* name, Data data){#if 0 // for debugging assert(name); if (true) // dump asn.1 stuff to debug file { ofstream strm(name, std::ios_base::trunc); if ( !strm ) { ErrLog( <<"Could not write to " << name ); } else { strm.write( data.data() , data.size() ); } strm.flush(); }#endif}X509* BaseSecurity::getDomainCert( const Data& domain ){ return mDomainCerts.count(domain) ? mDomainCerts[domain] : 0;}X509* BaseSecurity::getUserCert( const Data& aor ){ return mUserCerts.count(aor) ? mUserCerts[aor] : 0;}EVP_PKEY* BaseSecurity::getDomainKey( const Data& domain ){ return mDomainPrivateKeys.count(domain) ? mDomainPrivat
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -