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