const vector<string>& ExtensibleAttribute::getSerializedValues() const { if (m_serialized.empty()) { const char* formatter = m_obj["_formatter"].string(); if (formatter) { string msg = formatter; DDF val = m_obj.first().first(); while (!val.isnull()) { static const char* legal="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890_.[]"; m_serialized.push_back(string()); string& processed = m_serialized.back(); string::size_type i=0,start=0; while (start!=string::npos && start<msg.length() && (i=msg.find("$",start))!=string::npos) { if (i>start) processed += msg.substr(start,i-start); // append everything in between start=i+1; // move start to the beginning of the token name i=msg.find_first_not_of(legal,start); // find token delimiter if (i==start) { // append a non legal character processed+=msg[start++]; continue; } string tag = msg.substr(start,(i==string::npos) ? i : i-start); if (tag == "_string" && val.string()) { processed += val.string(); start=i; } else { DDF child = val.getmember(tag.c_str()); if (child.string()) processed += child.string(); else if (child.isstruct() && child["_string"].string()) processed += child["_string"].string(); start=i; } } if (start!=string::npos && start<msg.length()) processed += msg.substr(start,i); // append rest of string val = m_obj.first().next(); } } } return Attribute::getSerializedValues(); }
void AbstractHandler::preservePostData( const Application& application, const HTTPRequest& request, HTTPResponse& response, const char* relayState ) const { #ifdef HAVE_STRCASECMP if (strcasecmp(request.getMethod(), "POST")) return; #else if (stricmp(request.getMethod(), "POST")) return; #endif // No specs mean no save. const PropertySet* props=application.getPropertySet("Sessions"); pair<bool,const char*> mech = props->getString("postData"); if (!mech.first) { m_log.info("postData property not supplied, form data will not be preserved across SSO"); return; } DDF postData = getPostData(application, request); if (postData.isnull()) return; if (strstr(mech.second,"ss:") == mech.second) { mech.second+=3; if (!*mech.second) { postData.destroy(); throw ConfigurationException("Unsupported postData mechanism ($1).", params(1, mech.second - 3)); } string postkey; if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) { DDFJanitor postjan(postData); #ifndef SHIBSP_LITE StorageService* storage = application.getServiceProvider().getStorageService(mech.second); if (storage) { // Use a random key string rsKey; SAMLConfig::getConfig().generateRandomBytes(rsKey,20); rsKey = SAMLArtifact::toHex(rsKey); ostringstream out; out << postData; if (!storage->createString("PostData", rsKey.c_str(), out.str().c_str(), time(NULL) + 600)) throw IOException("Attempted to insert duplicate storage key."); postkey = string(mech.second-3) + ':' + rsKey; } else { m_log.error("storage-backed PostData mechanism with invalid StorageService ID (%s)", mech.second); } #endif } else if (SPConfig::getConfig().isEnabled(SPConfig::InProcess)) { DDF out,in = DDF("set::PostData").structure(); DDFJanitor jin(in),jout(out); in.addmember("id").string(mech.second); in.add(postData); out = application.getServiceProvider().getListenerService()->send(in); if (!out.isstring()) throw IOException("StorageService-backed PostData mechanism did not return a state key."); postkey = string(mech.second-3) + ':' + out.string(); } // Set a cookie with key info. pair<string,const char*> shib_cookie = getPostCookieNameProps(application, relayState); postkey += shib_cookie.second; response.setCookie(shib_cookie.first.c_str(), postkey.c_str()); } else { postData.destroy(); throw ConfigurationException("Unsupported postData mechanism ($1).", params(1,mech.second)); } }