https://issues.shibboleth.net/jira/browse/CPPOST-67
[shibboleth/cpp-opensaml.git] / saml / signature / ContentReference.cpp
1 /**
2  * Licensed to the University Corporation for Advanced Internet
3  * Development, Inc. (UCAID) under one or more contributor license
4  * agreements. See the NOTICE file distributed with this work for
5  * additional information regarding copyright ownership.
6  *
7  * UCAID licenses this file to you under the Apache License,
8  * Version 2.0 (the "License"); you may not use this file except
9  * in compliance with the License. You may obtain a copy of the
10  * License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing,
15  * software distributed under the License is distributed on an
16  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
17  * either express or implied. See the License for the specific
18  * language governing permissions and limitations under the License.
19  */
20
21 /**
22  * ContentReference.cpp
23  * 
24  * SAML-specific signature reference profile.
25  */
26  
27 #include "internal.h"
28 #include "signature/ContentReference.h"
29 #include "signature/SignableObject.h"
30
31 #include <xmltooling/signature/Signature.h>
32 #include <xercesc/util/XMLUniDefs.hpp>
33 #include <xsec/dsig/DSIGReference.hpp>
34 #include <xsec/dsig/DSIGSignature.hpp>
35 #include <xsec/dsig/DSIGTransformC14n.hpp>
36
37 using namespace opensaml;
38 using namespace xmltooling;
39 using namespace std;
40
41 void SignableObject::declareNonVisibleNamespaces() const
42 {
43     ContentReference* cr = getSignature() ? dynamic_cast<ContentReference*>(getSignature()->getContentReference()) : nullptr;
44
45     // Compute inclusive prefix set.
46     map<xstring,xstring> decls;
47     XMLHelper::getNonVisiblyUsedPrefixes(*this, decls);
48
49     for (map<xstring,xstring>::const_iterator decl = decls.begin(); decl != decls.end(); ++decl) {
50
51         // Pin it to the object root. An existing copy of the prefix on the root will take precedence.
52         addNamespace(Namespace(decl->second.c_str(), decl->first.c_str(), true, Namespace::NonVisiblyUsed));
53
54         // Add to content reference, if any.
55         if (cr)
56             cr->addInclusivePrefix(decl->first.c_str());
57     }
58 }
59
60 ContentReference::ContentReference(const SignableObject& signableObject)
61     : m_signableObject(signableObject), m_digest(nullptr), m_c14n(nullptr)
62 {
63 }
64
65 ContentReference::~ContentReference()
66 {
67 }
68
69 void ContentReference::createReferences(DSIGSignature* sig)
70 {
71     DSIGReference* ref = nullptr;
72     sig->setIdByAttributeName(false);
73     const XMLCh* id=m_signableObject.getXMLID();
74     if (!id || !*id)
75         ref=sig->createReference(&chNull, m_digest ? m_digest : DSIGConstants::s_unicodeStrURISHA1);  // whole doc reference
76     else {
77         XMLCh* buf=new XMLCh[XMLString::stringLen(id) + 2];
78         buf[0]=chPound;
79         buf[1]=chNull;
80         XMLString::catString(buf,id);
81         try {
82             ref=sig->createReference(buf, m_digest ? m_digest : DSIGConstants::s_unicodeStrURISHA1);
83             delete[] buf;
84         }
85         catch(...) {
86             delete[] buf;
87             throw;
88         }
89     }
90     
91     ref->appendEnvelopedSignatureTransform();
92     DSIGTransformC14n* c14n=ref->appendCanonicalizationTransform(m_c14n ? m_c14n : DSIGConstants::s_unicodeStrURIEXC_C14N_NOC);
93
94     if (!m_c14n || m_c14n == DSIGConstants::s_unicodeStrURIEXC_C14N_NOC || m_c14n == DSIGConstants::s_unicodeStrURIEXC_C14N_COM) {
95         // Build up the string of prefixes.
96         xstring prefixes;
97         static const XMLCh _default[] = { chPound, chLatin_d, chLatin_e, chLatin_f, chLatin_a, chLatin_u, chLatin_l, chLatin_t, chNull };
98         for (set<xstring>::const_iterator p = m_prefixes.begin(); p != m_prefixes.end(); ++p) {
99             prefixes += (p->empty() ? _default : p->c_str());
100             prefixes += chSpace;
101         }
102         if (!prefixes.empty()) {
103             prefixes.erase(prefixes.begin() + prefixes.size() - 1);
104             c14n->setInclusiveNamespaces(const_cast<XMLCh*>(prefixes.c_str()));
105         }
106     }
107 }
108
109 void ContentReference::addInclusivePrefix(const XMLCh* prefix)
110 {
111     m_prefixes.insert(prefix ? prefix : &chNull);
112 }
113
114 void ContentReference::setDigestAlgorithm(const XMLCh* digest)
115 {
116     m_digest = digest;
117 }
118
119 void ContentReference::setCanonicalizationMethod(const XMLCh* c14n)
120 {
121     m_c14n = c14n;
122 }