Reduce catch all handlers, and make them optional.
[shibboleth/cpp-sp.git] / test / shibtest.cpp
1 /*
2  *  Copyright 2001-2005 Internet2
3  * 
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 #include "../shib-target/shib-target.h"
18
19 using namespace std;
20 using namespace saml;
21 using namespace shibboleth;
22 using namespace shibtarget;
23
24 int main(int argc,char* argv[])
25 {
26     char* h_param=NULL;
27     char* q_param=NULL;
28     char* f_param=NULL;
29     char* a_param=NULL;
30     char* path=NULL;
31     char* config=NULL;
32
33     for (int i=1; i<argc; i++) {
34         if (!strcmp(argv[i],"-c") && i+1<argc)
35             config=argv[++i];
36         else if (!strcmp(argv[i],"-d") && i+1<argc)
37             path=argv[++i];
38         else if (!strcmp(argv[i],"-h") && i+1<argc)
39             h_param=argv[++i];
40         else if (!strcmp(argv[i],"-q") && i+1<argc)
41             q_param=argv[++i];
42         else if (!strcmp(argv[i],"-f") && i+1<argc)
43             f_param=argv[++i];
44         else if (!strcmp(argv[i],"-a") && i+1<argc)
45             a_param=argv[++i];
46     }
47
48     if (!h_param || !q_param) {
49         cerr << "usage: shibtest -h <handle> -q <origin_site> [-f <format URI> -a <application_id> -d <schema path> -c <config>]" << endl;
50         exit(0);
51     }
52     
53     if (!path)
54         path=getenv("SHIBSCHEMAS");
55     if (!path)
56         path=SHIB_SCHEMAS;
57     if (!config)
58         config=getenv("SHIBCONFIG");
59     if (!config)
60         config=SHIB_CONFIG;
61     if (!a_param)
62         a_param="default";
63
64     ShibTargetConfig& conf=ShibTargetConfig::getConfig();
65     conf.setFeatures(
66         ShibTargetConfig::Metadata |
67         ShibTargetConfig::Trust |
68         ShibTargetConfig::Credentials |
69         ShibTargetConfig::AAP |
70         ShibTargetConfig::GlobalExtensions |
71         ShibTargetConfig::Caching
72         );
73     if (!conf.init(path) || !conf.load(config))
74         return -10;
75
76     try {
77         const IApplication* app=conf.getINI()->getApplication(a_param);
78         if (!app)
79             throw SAMLException("specified <Application> section not found in configuration");
80
81         auto_ptr_XMLCh domain(q_param);
82         auto_ptr_XMLCh handle(h_param);
83         auto_ptr_XMLCh format(f_param);
84         auto_ptr_XMLCh resource(app->getString("providerId").second);
85
86         auto_ptr<SAMLRequest> req(
87             new SAMLRequest(
88                 new SAMLAttributeQuery(
89                     new SAMLSubject(
90                         new SAMLNameIdentifier(
91                             handle.get(),
92                             domain.get(),
93                             format.get() ? format.get() : Constants::SHIB_NAMEID_FORMAT_URI
94                             )
95                         ),
96                     resource.get(),
97                     app->getAttributeDesignators().clone()
98                     )
99                 )
100             );
101
102         Metadata m(app->getMetadataProviders());
103         const IEntityDescriptor* site=m.lookup(domain.get());
104         if (!site)
105             throw SAMLException("Unable to locate specified origin site's metadata.");
106
107         // Try to locate an AA role.
108         const IAttributeAuthorityDescriptor* AA=site->getAttributeAuthorityDescriptor(saml::XML::SAML11_PROTOCOL_ENUM);
109         if (!AA)
110             throw SAMLException("Unable to locate metadata for origin site's Attribute Authority.");
111
112         ShibHTTPHook::ShibHTTPHookCallContext ctx(app->getCredentialUse(site),AA);
113         Trust t(app->getTrustProviders());
114
115         SAMLResponse* response=NULL;
116         Iterator<const IEndpoint*> endpoints=AA->getAttributeServiceManager()->getEndpoints();
117         while (!response && endpoints.hasNext()) {
118             const IEndpoint* ep=endpoints.next();
119             try {
120                 // Get a binding object for this protocol.
121                 const SAMLBinding* binding = app->getBinding(ep->getBinding());
122                 if (!binding) {
123                     continue;
124                 }
125                 auto_ptr<SAMLResponse> r(binding->send(ep->getLocation(), *(req.get()), &ctx));
126                 if (r->isSigned() && !t.validate(*r,AA))
127                     throw TrustException("unable to verify signed response");
128                 response = r.release();
129             }
130             catch (SAMLException& e) {
131                 // Check for shib:InvalidHandle error and propagate it out.
132                 Iterator<saml::QName> codes=e.getCodes();
133                 if (codes.size()>1) {
134                     const saml::QName& code=codes[1];
135                     if (!XMLString::compareString(code.getNamespaceURI(),shibboleth::Constants::SHIB_NS) &&
136                         !XMLString::compareString(code.getLocalName(), shibboleth::Constants::InvalidHandle)) {
137                         codes.reset();
138                         throw InvalidHandleException(e.what(),params(),codes);
139                     }
140                 }
141             }
142         }
143
144         if (!response)
145             throw SAMLException("unable to successfully query for attributes");
146
147         // Run it through the AAP. Note that we could end up with an empty response!
148         Iterator<SAMLAssertion*> a=response->getAssertions();
149         for (unsigned long c=0; c < a.size();) {
150             try {
151                 AAP::apply(app->getAAPProviders(),*(a[c]),AA);
152                 c++;
153             }
154             catch (SAMLException&) {
155                 response->removeAssertion(c);
156             }
157         }
158
159         Iterator<SAMLAssertion*> i=response->getAssertions();
160         if (i.hasNext())
161         {
162             SAMLAssertion* a=i.next();
163             cout << "Issuer: "; xmlout(cout,a->getIssuer()); cout << endl;
164             const SAMLDateTime* exp=a->getNotOnOrAfter();
165             cout << "Expires: ";
166             if (exp)
167               xmlout(cout,exp->getRawData());
168             else
169                 cout << "None";
170             cout << endl;
171
172             Iterator<SAMLStatement*> j=a->getStatements();
173             if (j.hasNext())
174             {
175                 SAMLAttributeStatement* s=dynamic_cast<SAMLAttributeStatement*>(j.next());
176                 if (s)
177                 {
178                     const SAMLNameIdentifier* sub=s->getSubject()->getNameIdentifier();
179                     cout << "Format: "; xmlout(cout,sub->getFormat()); cout << endl;
180                     cout << "Domain: "; xmlout(cout,sub->getNameQualifier()); cout << endl;
181                     cout << "Handle: "; xmlout(cout,sub->getName()); cout << endl;
182
183                     Iterator<SAMLAttribute*> attrs=s->getAttributes();
184                     while (attrs.hasNext())
185                     {
186                         SAMLAttribute* attr=attrs.next();
187                         cout << "Attribute Name: "; xmlout(cout,attr->getName()); cout << endl;
188                         Iterator<const XMLCh*> vals=attr->getValues();
189                         while (vals.hasNext())
190                         {
191                             cout << "Attribute Value: ";
192                             xmlout(cout,vals.next());
193                             cout << endl;
194                         }
195                     }
196                 }
197             }
198         }
199     }
200     catch(SAMLException& e)
201     {
202         cerr << "caught a SAML exception: " << e.what() << endl;
203     }
204     catch(XMLException& e)
205     {
206         cerr << "caught an XML exception: "; xmlout(cerr,e.getMessage()); cerr << endl;
207     }
208
209     conf.shutdown();
210     return 0;
211 }