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