Updated to xsec 1.2
[shibboleth/sp.git] / test / shibtest.cpp
1 /*
2  * The Shibboleth License, Version 1.
3  * Copyright (c) 2002
4  * University Corporation for Advanced Internet Development, Inc.
5  * All rights reserved
6  *
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions are met:
10  *
11  * Redistributions of source code must retain the above copyright notice, this
12  * list of conditions and the following disclaimer.
13  *
14  * Redistributions in binary form must reproduce the above copyright notice,
15  * this list of conditions and the following disclaimer in the documentation
16  * and/or other materials provided with the distribution, if any, must include
17  * the following acknowledgment: "This product includes software developed by
18  * the University Corporation for Advanced Internet Development
19  * <http://www.ucaid.edu>Internet2 Project. Alternately, this acknowledegement
20  * may appear in the software itself, if and wherever such third-party
21  * acknowledgments normally appear.
22  *
23  * Neither the name of Shibboleth nor the names of its contributors, nor
24  * Internet2, nor the University Corporation for Advanced Internet Development,
25  * Inc., nor UCAID may be used to endorse or promote products derived from this
26  * software without specific prior written permission. For written permission,
27  * please contact shibboleth@shibboleth.org
28  *
29  * Products derived from this software may not be called Shibboleth, Internet2,
30  * UCAID, or the University Corporation for Advanced Internet Development, nor
31  * may Shibboleth appear in their name, without prior written permission of the
32  * University Corporation for Advanced Internet Development.
33  *
34  *
35  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
36  * AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
37  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
38  * PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE DISCLAIMED AND THE ENTIRE RISK
39  * OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS WITH LICENSEE.
40  * IN NO EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY
41  * CORPORATION FOR ADVANCED INTERNET DEVELOPMENT, INC. BE LIABLE FOR ANY DIRECT,
42  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
43  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
44  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
46  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
47  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
48  */
49
50
51 #include "../shib-target/shib-target.h"
52
53 using namespace std;
54 using namespace saml;
55 using namespace shibboleth;
56 using namespace shibtarget;
57
58 int main(int argc,char* argv[])
59 {
60     char* h_param=NULL;
61     char* q_param=NULL;
62     char* f_param=NULL;
63     char* a_param=NULL;
64     char* path=NULL;
65     char* config=NULL;
66
67     for (int i=1; i<argc; i++) {
68         if (!strcmp(argv[i],"-c") && i+1<argc)
69             config=argv[++i];
70         else if (!strcmp(argv[i],"-d") && i+1<argc)
71             path=argv[++i];
72         else if (!strcmp(argv[i],"-h") && i+1<argc)
73             h_param=argv[++i];
74         else if (!strcmp(argv[i],"-q") && i+1<argc)
75             q_param=argv[++i];
76         else if (!strcmp(argv[i],"-f") && i+1<argc)
77             f_param=argv[++i];
78         else if (!strcmp(argv[i],"-a") && i+1<argc)
79             a_param=argv[++i];
80     }
81
82     if (!h_param || !q_param) {
83         cerr << "usage: shibtest -h <handle> -q <origin_site> [-f <format URI> -a <application_id> -d <schema path> -c <config>]" << endl;
84         exit(0);
85     }
86     
87     if (!path)
88         path=getenv("SHIBSCHEMAS");
89     if (!path)
90         path=SHIB_SCHEMAS;
91     if (!config)
92         config=getenv("SHIBCONFIG");
93     if (!config)
94         config=SHIB_CONFIG;
95     if (!a_param)
96         a_param="default";
97
98     ShibTargetConfig& conf=ShibTargetConfig::getConfig();
99     conf.setFeatures(
100         ShibTargetConfig::Metadata |
101         ShibTargetConfig::Trust |
102         ShibTargetConfig::Credentials |
103         ShibTargetConfig::AAP |
104         ShibTargetConfig::GlobalExtensions |
105         ShibTargetConfig::Caching
106         );
107     if (!conf.init(path) || !conf.load(config))
108         return -10;
109
110     try {
111         const IApplication* app=conf.getINI()->getApplication(a_param);
112         if (!app)
113             throw SAMLException("specified <Application> section not found in configuration");
114
115         auto_ptr_XMLCh domain(q_param);
116         auto_ptr_XMLCh handle(h_param);
117         auto_ptr_XMLCh format(f_param);
118         auto_ptr_XMLCh resource(app->getString("providerId").second);
119
120         auto_ptr<SAMLRequest> req(
121             new SAMLRequest(
122                 new SAMLAttributeQuery(
123                     new SAMLSubject(
124                         new SAMLNameIdentifier(
125                             handle.get(),
126                             domain.get(),
127                             format.get() ? format.get() : Constants::SHIB_NAMEID_FORMAT_URI
128                             )
129                         ),
130                     resource.get(),
131                     app->getAttributeDesignators().clone()
132                     )
133                 )
134             );
135
136         Metadata m(app->getMetadataProviders());
137         const IEntityDescriptor* site=m.lookup(domain.get());
138         if (!site)
139             throw SAMLException("Unable to locate specified origin site's metadata.");
140
141         // Try to locate an AA role.
142         const IAttributeAuthorityDescriptor* AA=site->getAttributeAuthorityDescriptor(saml::XML::SAML11_PROTOCOL_ENUM);
143         if (!AA)
144             throw SAMLException("Unable to locate metadata for origin site's Attribute Authority.");
145
146         ShibHTTPHook::ShibHTTPHookCallContext ctx(app->getCredentialUse(site),AA);
147         Trust t(app->getTrustProviders());
148
149         SAMLResponse* response=NULL;
150         Iterator<const IEndpoint*> endpoints=AA->getAttributeServiceManager()->getEndpoints();
151         while (!response && endpoints.hasNext()) {
152             const IEndpoint* ep=endpoints.next();
153             try {
154                 // Get a binding object for this protocol.
155                 const SAMLBinding* binding = app->getBinding(ep->getBinding());
156                 if (!binding) {
157                     continue;
158                 }
159                 auto_ptr<SAMLResponse> r(binding->send(ep->getLocation(), *(req.get()), &ctx));
160                 if (r->isSigned() && !t.validate(*r,AA))
161                     throw TrustException("unable to verify signed response");
162                 response = r.release();
163             }
164             catch (SAMLException& e) {
165                 // Check for shib:InvalidHandle error and propagate it out.
166                 Iterator<saml::QName> codes=e.getCodes();
167                 if (codes.size()>1) {
168                     const saml::QName& code=codes[1];
169                     if (!XMLString::compareString(code.getNamespaceURI(),shibboleth::Constants::SHIB_NS) &&
170                         !XMLString::compareString(code.getLocalName(), shibboleth::Constants::InvalidHandle)) {
171                         codes.reset();
172                         throw InvalidHandleException(e.what(),params(),codes);
173                     }
174                 }
175             }
176         }
177
178         if (!response)
179             throw SAMLException("unable to successfully query for attributes");
180
181         // Run it through the AAP. Note that we could end up with an empty response!
182         Iterator<SAMLAssertion*> a=response->getAssertions();
183         for (unsigned long c=0; c < a.size();) {
184             try {
185                 AAP::apply(app->getAAPProviders(),*(a[c]),AA);
186                 c++;
187             }
188             catch (SAMLException&) {
189                 response->removeAssertion(c);
190             }
191         }
192
193         Iterator<SAMLAssertion*> i=response->getAssertions();
194         if (i.hasNext())
195         {
196             SAMLAssertion* a=i.next();
197             cout << "Issuer: "; xmlout(cout,a->getIssuer()); cout << endl;
198             const SAMLDateTime* exp=a->getNotOnOrAfter();
199             cout << "Expires: ";
200             if (exp)
201               xmlout(cout,exp->getRawData());
202             else
203                 cout << "None";
204             cout << endl;
205
206             Iterator<SAMLStatement*> j=a->getStatements();
207             if (j.hasNext())
208             {
209                 SAMLAttributeStatement* s=dynamic_cast<SAMLAttributeStatement*>(j.next());
210                 if (s)
211                 {
212                     const SAMLNameIdentifier* sub=s->getSubject()->getNameIdentifier();
213                     cout << "Format: "; xmlout(cout,sub->getFormat()); cout << endl;
214                     cout << "Domain: "; xmlout(cout,sub->getNameQualifier()); cout << endl;
215                     cout << "Handle: "; xmlout(cout,sub->getName()); cout << endl;
216
217                     Iterator<SAMLAttribute*> attrs=s->getAttributes();
218                     while (attrs.hasNext())
219                     {
220                         SAMLAttribute* attr=attrs.next();
221                         cout << "Attribute Name: "; xmlout(cout,attr->getName()); cout << endl;
222                         Iterator<const XMLCh*> vals=attr->getValues();
223                         while (vals.hasNext())
224                         {
225                             cout << "Attribute Value: ";
226                             xmlout(cout,vals.next());
227                             cout << endl;
228                         }
229                     }
230                 }
231             }
232         }
233     }
234     catch(SAMLException& e)
235     {
236         cerr << "caught a SAML exception: " << e.what() << endl;
237     }
238     catch(XMLException& e)
239     {
240         cerr << "caught an XML exception: "; xmlout(cerr,e.getMessage()); cerr << endl;
241     }
242
243     conf.shutdown();
244     return 0;
245 }