2 * shibrpc-server.cpp -- SHIBRPC Server implementation. Originally created
3 * as shibrpc-server-stubs.c; make sure that the function
4 * prototypes here match those in shibrpc.x.
6 * Created by: Derek Atkins <derek@ihtfp.com>
12 #include "shib-target.h"
14 #include <log4cpp/Category.hh>
19 using namespace shibboleth;
20 using namespace shibtarget;
23 static std::string get_threadid (const char* proc)
25 static u_long counter = 0;
27 buf << "[" << counter++ << "] " << proc;
31 static log4cpp::Category& get_category (void)
33 string ctx = "shibtarget.rpc-server";
34 return log4cpp::Category::getInstance(ctx);
38 shibrpc_ping_1_svc(int *argp, int *result, struct svc_req *rqstp)
45 shibrpc_session_is_valid_1_svc(shibrpc_session_is_valid_args_1 *argp,
46 shibrpc_session_is_valid_ret_1 *result,
47 struct svc_req *rqstp)
49 log4cpp::Category& log = get_category();
50 string ctx = get_threadid("session_is_valid");
53 if (!argp || !result) {
54 log.error ("RPC Argument Error");
58 memset (result, 0, sizeof (*result));
60 log.debug ("checking: %s@%s (checkAddr=%s)",
61 argp->cookie.cookie, argp->cookie.client_addr,
62 argp->checkIPAddress ? "true" : "false");
64 // See if the cookie exists...
65 CCacheEntry *entry = g_shibTargetCCache->find(argp->cookie.cookie);
67 // If not, leave now..
69 log.debug ("Not found");
70 result->status = SHIBRPC_NO_SESSION;
71 result->error_msg = strdup("No session exists for this cookie");
75 // Verify the address is the same
76 if (argp->checkIPAddress) {
77 log.debug ("Checking address against %s", entry->getClientAddress());
78 if (strcmp (argp->cookie.client_addr, entry->getClientAddress())) {
79 log.debug ("IP Address mismatch");
80 result->status = SHIBRPC_IPADDR_MISMATCH;
82 strdup ("Your IP address does not match the address in the original authentication.");
83 g_shibTargetCCache->remove (argp->cookie.cookie);
88 // and that the session is still valid...
89 if (!entry->isSessionValid(argp->lifetime, argp->timeout)) {
90 log.debug ("Session expired");
91 result->status = SHIBRPC_SESSION_EXPIRED;
92 result->error_msg = strdup ("Your session has expired. Re-authenticate.");
93 g_shibTargetCCache->remove (argp->cookie.cookie);
97 // ok, we've succeeded..
98 result->status = SHIBRPC_OK;
99 result->error_msg = strdup("");
100 log.debug ("session ok");
105 shibrpc_new_session_1_svc(shibrpc_new_session_args_1 *argp,
106 shibrpc_new_session_ret_1 *result, struct svc_req *rqstp)
108 log4cpp::Category& log = get_category();
109 string ctx = get_threadid("new_session");
112 if (!argp || !result) {
113 log.error ("Invalid RPC Arguments");
117 // Initialize the result structure
118 memset (result, 0, sizeof(*result));
119 result->cookie = strdup ("");
121 log.debug ("creating session for %s", argp->client_addr);
122 log.debug ("shire location: %s", argp->shire_location);
124 XMLByte* post=reinterpret_cast<XMLByte*>(argp->saml_post);
125 auto_ptr<XMLCh> location(XMLString::transcode(argp->shire_location));
127 // Pull in the Policies
128 static const XMLCh* clubShib[] = {shibboleth::Constants::POLICY_CLUBSHIB};
129 ArrayIterator<const XMLCh*> policies(clubShib);
131 // And grab the Profile
132 // XXX: Create a "Global" POSTProfile instance per location...
133 log.debug ("create the POST profile (%d policies)", policies.size());
134 ShibPOSTProfile *profile =
135 ShibPOSTProfileFactory::getInstance(policies,
136 ShibConfig::getConfig().origin_mapper,
140 SAMLResponse* r = NULL;
141 SAMLAuthenticationStatement* auth_st = NULL;
147 // Make sure we've got a profile
149 throw ShibTargetException(SHIBRPC_INTERNAL_ERROR,
150 "Failed to obtain the profile");
152 // Try and accept the response...
153 log.debug ("Trying to accept the post");
154 r = profile->accept(post);
156 // Make sure we got a response
158 throw ShibTargetException(SHIBRPC_RESPONSE_MISSING,
159 "Failed to accept the response.");
161 // Find the SSO Assertion
162 log.debug ("Get the SSOAssertion");
163 SAMLAssertion* ssoAssertion = profile->getSSOAssertion(*r);
165 // verify that we obtained an assertion
167 throw ShibTargetException(SHIBRPC_ASSERTION_MISSING,
168 "Cannot find SSO Assertion");
170 // Check against the replay cache
171 log.debug ("check replay cache");
172 if (profile->checkReplayCache(*ssoAssertion) == false)
173 throw ShibTargetException(SHIBRPC_ASSERTION_REPLAYED,
174 "Duplicate assertion found.");
176 // Get the authentication statement we need.
177 log.debug ("get SSOStatement");
178 auth_st = profile->getSSOStatement(*ssoAssertion);
180 // Verify we obtained an authentication statement
182 throw ShibTargetException(SHIBRPC_AUTHSTATEMENT_MISSING,
183 "Processing was successful but no authentication statement was found.");
185 // Maybe verify the origin address....
186 if (argp->checkIPAddress) {
187 log.debug ("check IP Address");
189 // Verify the client address exists
190 const XMLCh* ip = auth_st->getSubjectIP();
192 throw ShibTargetException(SHIBRPC_IPADDR_MISSING,
193 "The IP Address provided by your origin site was missing.");
195 log.debug ("verify client address");
196 // Verify the client address matches authentication
197 auto_ptr<char> this_ip(XMLString::transcode(ip));
198 if (strcmp (argp->client_addr, this_ip.get()))
199 throw ShibTargetException(SHIBRPC_IPADDR_MISMATCH,
200 "The IP address provided by your origin site did not match your current address. To correct this problem you may need to bypass a local proxy server.");
203 catch (SAMLException &e)
205 log.error ("received SAML exception");
208 throw ShibTargetException (SHIBRPC_SAML_EXCEPTION, os.str());
210 catch (XMLException &e)
212 log.error ("received XML exception");
213 auto_ptr<char> msg(XMLString::transcode(e.getMessage()));
214 throw ShibTargetException (SHIBRPC_XML_EXCEPTION, msg.get());
217 catch (ShibTargetException &e)
219 log.info ("FAILED: %s", e.what());
221 result->status = e.which();
222 result->error_msg = strdup(e.what());
228 log.error ("Unknown error");
230 result->status = SHIBRPC_UNKNOWN_ERROR;
231 result->error_msg = strdup("An unknown exception occurred");
236 // It passes all our tests -- create a new session.
237 log.info ("Creating new session");
239 SAMLAuthenticationStatement* as=static_cast<SAMLAuthenticationStatement*>(auth_st->clone());
240 CCacheEntry* session = CCacheEntry::getInstance (as, argp->client_addr);
242 // Create a new cookie
244 auto_ptr<char> c(XMLString::transcode(id));
245 char *cookie = c.get();
247 // Cache this session with the cookie
248 g_shibTargetCCache->insert(cookie, session);
250 // Delete the response...
253 // And let the user know.
254 free (result->cookie);
255 result->cookie = strdup(cookie);
256 result->status = SHIBRPC_OK;
257 result->error_msg = strdup("");
259 log.debug ("new session id: %s", cookie);
264 shibrpc_get_assertions_1_svc(shibrpc_get_assertions_args_1 *argp,
265 shibrpc_get_assertions_ret_1 *result, struct svc_req *rqstp)
267 log4cpp::Category& log = get_category();
268 string ctx = get_threadid("get_assertions");
271 if (!argp || !result) {
272 log.error ("Invalid RPC arguments");
276 memset (result, 0, sizeof (*result));
278 log.debug ("get attrs for client at %s", argp->cookie.client_addr);
279 log.debug ("cookie: %s", argp->cookie.cookie);
280 log.debug ("resource: %s", argp->url);
283 CCacheEntry* entry = g_shibTargetCCache->find(argp->cookie.cookie);
285 // If it does not exist, leave now..
287 log.error ("No Session");
288 result->status = SHIBRPC_NO_SESSION;
289 result->error_msg = strdup("getattrs Internal error: no session");
293 // Validate the client address (again?)
294 if (argp->checkIPAddress &&
295 strcmp (argp->cookie.client_addr, entry->getClientAddress())) {
296 log.error ("IP Mismatch");
297 result->status = SHIBRPC_IPADDR_MISMATCH;
299 strdup("Your IP address does not match the address in the original authentication.");
304 // grab the attributes for this resource
305 Resource resource(argp->url);
306 Iterator<SAMLAssertion*> iter = entry->getAssertions(resource);
307 u_int size = iter.size();
308 result->assertions.assertions_len = size;
310 // if we have assertions...
313 // Build the response section
314 ShibRpcAssertion_1* av =
315 (ShibRpcAssertion_1*) malloc (size * sizeof (ShibRpcAssertion_1));
316 result->assertions.assertions_val = av;
318 // and then serialize them all...
320 while (iter.hasNext()) {
321 SAMLAssertion* as = iter.next();
324 av[i++].assertion = strdup(os.str().c_str());
327 } catch (SAMLException& e) {
328 log.error ("received SAML exception");
331 result->status = SHIBRPC_SAML_EXCEPTION;
332 result->error_msg = strdup(os.str().c_str());
337 result->status = SHIBRPC_OK;
338 result->error_msg = strdup("");
340 log.debug ("returning");
345 shibrpc_prog_1_freeresult (SVCXPRT *transp, xdrproc_t xdr_result, caddr_t result)
347 xdr_free (xdr_result, result);
350 * Insert additional freeing code here, if needed