📄 security.cxx
字号:
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 + -