Moved artifact source code into binding folders.
[shibboleth/cpp-opensaml.git] / saml / SAMLConfig.cpp
1
2 /*
3  *  Copyright 2001-2006 Internet2
4  * 
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17
18 /**
19  * SAMLConfig.cpp
20  * 
21  * Library configuration 
22  */
23
24 #include "internal.h"
25 #include "exceptions.h"
26 #include "SAMLConfig.h"
27 #include "binding/SAMLArtifact.h"
28 #include "saml1/core/Assertions.h"
29 #include "saml1/core/Protocols.h"
30 #include "saml2/core/Protocols.h"
31 #include "saml2/metadata/Metadata.h"
32 #include "saml2/metadata/MetadataProvider.h"
33 #include "security/TrustEngine.h"
34 #include "util/SAMLConstants.h"
35
36 #include <xmltooling/XMLToolingConfig.h>
37 #include <xmltooling/signature/Signature.h>
38 #include <xmltooling/util/NDC.h>
39
40 #include <log4cpp/Category.hh>
41 #include <xsec/enc/XSECCryptoException.hpp>
42 #include <xsec/enc/XSECCryptoProvider.hpp>
43 #include <xsec/utils/XSECPlatformUtils.hpp>
44 #include <openssl/err.h>
45
46 using namespace opensaml;
47 using namespace xmlsignature;
48 using namespace xmltooling;
49 using namespace log4cpp;
50 using namespace std;
51
52 // Expose entry points when used as an extension library
53
54 extern "C" int SAML_API xmltooling_extension_init(void*)
55 {
56     if (SAMLConfig::getConfig().init(false))
57         return 0;
58     return -1;
59 }
60
61 extern "C" void SAML_API xmltooling_extension_term()
62 {
63     SAMLConfig::getConfig().term(false);
64 }
65
66 DECL_EXCEPTION_FACTORY(ArtifactException,opensaml);
67 DECL_EXCEPTION_FACTORY(MetadataFilterException,opensaml::saml2md);
68
69 namespace opensaml {
70    SAMLInternalConfig g_config;
71 }
72
73 SAMLConfig& SAMLConfig::getConfig()
74 {
75     return g_config;
76 }
77
78 SAMLInternalConfig& SAMLInternalConfig::getInternalConfig()
79 {
80     return g_config;
81 }
82
83 bool SAMLInternalConfig::init(bool initXMLTooling)
84 {
85 #ifdef _DEBUG
86     xmltooling::NDC ndc("init");
87 #endif
88     Category& log=Category::getInstance(SAML_LOGCAT".SAMLConfig");
89     log.debug("library initialization started");
90
91     if (initXMLTooling) {
92         XMLToolingConfig::getConfig().init();
93         log.debug("XMLTooling library initialized");
94     }
95
96     REGISTER_EXCEPTION_FACTORY(ArtifactException,opensaml);
97     REGISTER_EXCEPTION_FACTORY(MetadataFilterException,opensaml::saml2md);
98
99     registerSAMLArtifacts();
100     saml1::registerAssertionClasses();
101     saml1p::registerProtocolClasses();
102     saml2::registerAssertionClasses();
103     saml2p::registerProtocolClasses();
104     saml2md::registerMetadataClasses();
105     saml2md::registerMetadataProviders();
106     saml2md::registerMetadataFilters();
107     registerTrustEngines();
108
109     log.info("library initialization complete");
110     return true;
111 }
112
113 void SAMLInternalConfig::term(bool termXMLTooling)
114 {
115 #ifdef _DEBUG
116     xmltooling::NDC ndc("term");
117 #endif
118     Category& log=Category::getInstance(SAML_LOGCAT".SAMLConfig");
119
120     saml1::AssertionSchemaValidators.destroyValidators();
121     saml1p::ProtocolSchemaValidators.destroyValidators();
122     saml2::AssertionSchemaValidators.destroyValidators();
123     saml2md::MetadataSchemaValidators.destroyValidators();
124     
125     SAMLArtifactManager.deregisterFactories();
126     MetadataFilterManager.deregisterFactories();
127     MetadataProviderManager.deregisterFactories();
128     TrustEngineManager.deregisterFactories();
129
130     if (termXMLTooling) {
131         XMLToolingConfig::getConfig().term();
132         log.debug("XMLTooling library shut down");
133     }
134     log.info("library shutdown complete");
135 }
136
137 void SAMLInternalConfig::generateRandomBytes(void* buf, unsigned int len)
138 {
139     try {
140         if (XSECPlatformUtils::g_cryptoProvider->getRandom(reinterpret_cast<unsigned char*>(buf),len)<len)
141             throw XMLSecurityException("Unable to generate random data; was PRNG seeded?");
142     }
143     catch (XSECCryptoException& e) {
144         throw XMLSecurityException("Unable to generate random data: $1",params(1,e.getMsg()));
145     }
146 }
147
148 void SAMLInternalConfig::generateRandomBytes(std::string& buf, unsigned int len)
149 {
150     buf.erase();
151     auto_ptr<unsigned char> hold(new unsigned char[len]);
152     generateRandomBytes(hold.get(),len);
153     for (unsigned int i=0; i<len; i++)
154         buf+=(hold.get())[i];
155 }
156
157 XMLCh* SAMLInternalConfig::generateIdentifier()
158 {
159     unsigned char key[17];
160     generateRandomBytes(key,16);
161     
162     char hexform[34];
163     sprintf(hexform,"_%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
164             key[0],key[1],key[2],key[3],key[4],key[5],key[6],key[7],
165             key[8],key[9],key[10],key[11],key[12],key[13],key[14],key[15]);
166     hexform[33]=0;
167     return XMLString::transcode(hexform);
168 }
169
170 string SAMLInternalConfig::hashSHA1(const char* s, bool toHex)
171 {
172     static char DIGITS[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
173
174     auto_ptr<XSECCryptoHash> hasher(XSECPlatformUtils::g_cryptoProvider->hashSHA1());
175     if (hasher.get()) {
176         auto_ptr<char> dup(strdup(s));
177         unsigned char buf[21];
178         hasher->hash(reinterpret_cast<unsigned char*>(dup.get()),strlen(dup.get()));
179         if (hasher->finish(buf,20)==20) {
180             string ret;
181             if (toHex) {
182                 for (unsigned int i=0; i<20; i++) {
183                     ret+=(DIGITS[((unsigned char)(0xF0 & buf[i])) >> 4 ]);
184                     ret+=(DIGITS[0x0F & buf[i]]);
185                 }
186             }
187             else {
188                 for (unsigned int i=0; i<20; i++) {
189                     ret+=buf[i];
190                 }
191             }
192             return ret;
193         }
194     }
195     throw XMLSecurityException("Unable to generate SHA-1 hash.");
196 }
197
198 void opensaml::log_openssl()
199 {
200     const char* file;
201     const char* data;
202     int flags,line;
203
204     unsigned long code=ERR_get_error_line_data(&file,&line,&data,&flags);
205     while (code) {
206         Category& log=Category::getInstance("OpenSSL");
207         log.errorStream() << "error code: " << code << " in " << file << ", line " << line << CategoryStream::ENDLINE;
208         if (data && (flags & ERR_TXT_STRING))
209             log.errorStream() << "error data: " << data << CategoryStream::ENDLINE;
210         code=ERR_get_error_line_data(&file,&line,&data,&flags);
211     }
212 }