SecurityPolicyRule是安全策略的基类,之后派生了若干个子类,每个子类处理相应的规则,如AudienceRestriction、ConditionsRule等。SecurityPolicyRule中最为关键的函数是evalute,其验证输入信息是否符合相应的安全策略要求。
saml2的断言:调用evaluate验证是否合规
ConditionsRule::evaluate()
{
//首先验证时间是否正确,此处省略代码
conds->getAudienceRestrictions(); 对该函数返回的vector中的每个元素,调用evaluate(),验证是否符合;//然后验证听众是否符合
conds->getOneTimeUses(); 对该函数返回的vector中的每个元素,调用evaluate(),验证是否符合;//此后再验证OneTimeUse是否符合
conds->getProxyRestrictions(); 对该函数返回的vector中的每个元素,调用evaluate(),验证是否符合;//此后再验证ProxyRestriction是否符合
conds->getConditions();对该函数返回的vector中的每个元素,调用evaluate(),验证是否符合;//最后调用基类,验证基类的规则是否符合
}
saml1的断言:调用evaluate验证是否合规
{
//首先验证时间是否正确,此处省略代码
conds->getAudienceRestrictionConditions();对该函数返回的vector中的每个元素,调用evaluate(),验证是否符合;//然后验证听众是否符合
conds->getDoNotCacheConditions(); 对该函数返回的vector中的每个元素,调用evaluate(),验证是否符合;//然后验证DoNotCacheCondition是否符合
conds->getConditions()对该函数返回的vector中的每个元素,调用evaluate(),验证是否符合;//最后调用基类,验证基类的规则是否符合 --可能是用户的基类
}
IgnoreRule 忽略指定的规则
SAML1-->binding
SAML1ArtifactDecoder.cpp
xmltooling::XMLObject* decode( std::string& relayState, const GenericRequest& genericRequest, SecurityPolicy& policy) const
{
const HTTPRequest* httpRequest=dynamic_cast(&genericRequest); //将request转变为HTTPRequest
//从上面解析得到的httpRequest中解析得到SAMLart或TARGET参数
relayState = TARGET;
//验证policy中是否提供artifactResolver和metadataProvider实现
//对SAMLart vector中的每个元素,验证是否是重放攻击,如果不是重放,则调用artifacts.push_back(SAMLArtifact::parse(*raw));将其压栈
policy.setIssuer(provider.first->getEntityID());
policy.setIssuerMetadata(provider.second); //设置策略的issuer
auto_ptr response( m_artifactResolver->resolve(artifactptrs, dynamic_cast(*provider.second), policy) ); //构造应答
}
SAML1ArtifactEncoder.cpp
long encode(GenericResponse& genericResponse,
XMLObject* xmlObject,
const char* destination,
const EntityDescriptor* recipient=nullptr,
const char* relayState=nullptr,
const ArtifactGenerator* artifactGenerator=nullptr,
const Credential* credential=nullptr,
const XMLCh* signatureAlg=nullptr,
const XMLCh* digestAlg=nullptr
) const
{
HTTPResponse* httpResponse=dynamic_cast(&genericResponse); //将通用的应答转化成httpResponse
auto_ptr artifact(artifactGenerator->generateSAML1Artifact(recipient));
mapper->storeContent(xmlObject, artifact.get(), recipientID.get()); //存储assertion
loc = loc + "SAMLart=" + escaper->encode(artifact->encode().c_str()) + "&TARGET=" + escaper->encode(relayState);
httpResponse->sendRedirect(loc.c_str()); //生成重定向
}
SAML1MessageDecoder.cpp
void SAML1MessageDecoder::extractMessageDetails(const XMLObject& message, const GenericRequest& req, const XMLCh* protocol, SecurityPolicy& policy)
{//根据message中的内容,确定是request还是response,
if (XMLString::equals(q.getLocalPart(), Request::LOCAL_NAME))
request = dynamic_cast(&message);
if (!request && XMLString::equals(q.getLocalPart(), Response::LOCAL_NAME))
response = dynamic_cast(&message);
const RootObject* root = request ? static_cast(request) : static_cast(response); //解析成树的结构
// Extract message details.
policy.setMessageID(root->getID());
policy.setIssueInstant(root->getIssueInstantEpoch());
policy.setIssuer(issuer); //SAML1中仅response中有issuer的信息,issuer的信息通过assertion提取获得
policy.setIssuerMetadata(entity.second);
}
SAML1POSTDecoder.cpp
XMLObject* SAML1POSTDecoder::decode(
string& relayState,
const GenericRequest& genericRequest,
SecurityPolicy& policy
) const
{
const HTTPRequest* httpRequest=dynamic_cast(&genericRequest);
if (strcmp(httpRequest->getMethod(),"POST"))
const char* samlResponse = httpRequest->getParameter("SAMLResponse");
const char* TARGET = httpRequest->getParameter("TARGET");
//作为SAML 请求应包含TARGET,作为应答应包含SAMLResponse
relayState = TARGET;
policy.evaluate(*response,&genericRequest);
auto_ptr_char recipient(response->getRecipient());
const char* recipient2 = httpRequest->getRequestURL(); //检查接收地址
}
SAML1POSTEncoder.cpp
Signature* sig = SignatureBuilder::buildSignature();
response->setSignature(sig);
// Sign response while marshalling. vectorsigs(1,sig);
rootElement = response->marshall((DOMDocument*)nullptr,&sigs,credential);
SAML1SOAPClient.cpp
void SAML1 SOAPClient::sendSAML(Request* request, const char* from, MetadataCredentialCriteria& to, const char* endpoint)
{
auto_ptrenv(EnvelopeBuilder::buildEnvelope());
Body* body = BodyBuilder::buildBody();
env->setBody(body);
body->getUnknownXMLObjects().push_back(request);
m_soaper.send(*env.get(), from, to, endpoint);
m_correlate = XMLString::replicate(request->getRequestID());
}
Response* SAML1SOAPClient::receiveSAML()
{
auto_ptr env(m_soaper.receive());
m_soaper.getPolicy().evaluate(*response);
}
SAML1SOAPDecoder.cpp
XMLObject* SAML1SOAPDecoder::decode(
string& relayState,
const GenericRequest& genericRequest,
SecurityPolicy& policy
) const
{
string s = genericRequest.getContentType();
const char* data = genericRequest.getRequestBody();
Envelope* env = dynamic_cast(xmlObject.get());
SchemaValidators.validate(env);
policy.evaluate(*env,&genericRequest);
policy.evaluate(*request,&genericRequest);
}
SAML1SOAPEncoder.cpp
long SAML1SOAPEncoder::encode(
GenericResponse& genericResponse,
XMLObject* xmlObject,
const char* destination,
const EntityDescriptor* recipient,
const char* relayState,
const ArtifactGenerator* artifactGenerator,
const Credential* credential,
const XMLCh* signatureAlg,
const XMLCh* digestAlg
) const
{
genericResponse.setContentType("text/xml");
httpResponse->setResponseHeader("Expires", "01-Jan-1997 12:00:00 GMT");
httpResponse->setResponseHeader("Cache-Control", "no-cache, no-store, must-revalidate, private");
httpResponse->setResponseHeader("Pragma", "no-cache");
Signature* sig = SignatureBuilder::buildSignature();
response->setSignature(sig);
if (signatureAlg)
sig->setSignatureAlgorithm(signatureAlg);
if (digestAlg) {
opensaml::ContentReference* cr = dynamic_cast(sig->getContentReference());
if (cr)
cr->setDigestAlgorithm(digestAlg);
}
}
SAML1-->Core
AssertionSchemaValidator.cpp中的 registerAssertionClasses()特别重要,其通过一系列宏定义的调用,注册所有的元素。
SAML1-->profile
AssertionValidator -- SAML 1.x basic assertion validator provides time and audience condition checking.
/* In addition to standard core requirements for validity, SSO assertions MUST have NotBefore/NotOnOrAfter attributes and each subject statement; MUST be confirmable via bearer or artifact method. */
class SAML_API BrowserSSOProfileValidator : public AssertionValidator