Exemplo n.º 1
0
void AbstractHandler::recoverRelayState(
    const Application& application, const HTTPRequest& request, HTTPResponse& response, string& relayState, bool clear
    ) const
{
    SPConfig& conf = SPConfig::getConfig();

    // Look for StorageService-backed state of the form "ss:SSID:key".
    const char* state = relayState.c_str();
    if (strstr(state,"ss:")==state) {
        state += 3;
        const char* key = strchr(state,':');
        if (key) {
            string ssid = relayState.substr(3, key - state);
            key++;
            if (!ssid.empty() && *key) {
                if (conf.isEnabled(SPConfig::OutOfProcess)) {
#ifndef SHIBSP_LITE
                    StorageService* storage = conf.getServiceProvider()->getStorageService(ssid.c_str());
                    if (storage) {
                        ssid = key;
                        if (storage->readString("RelayState",ssid.c_str(),&relayState)>0) {
                            if (clear)
                                storage->deleteString("RelayState",ssid.c_str());
                            return;
                        }
                        else
                            relayState.erase();
                    }
                    else {
                        m_log.error("Storage-backed RelayState with invalid StorageService ID (%s)", ssid.c_str());
                        relayState.erase();
                    }
#endif
                }
                else if (conf.isEnabled(SPConfig::InProcess)) {
                    DDF out,in = DDF("get::RelayState").structure();
                    in.addmember("id").string(ssid.c_str());
                    in.addmember("key").string(key);
                    in.addmember("clear").integer(clear ? 1 : 0);
                    DDFJanitor jin(in),jout(out);
                    out = application.getServiceProvider().getListenerService()->send(in);
                    if (!out.isstring()) {
                        m_log.error("StorageService-backed RelayState mechanism did not return a state value.");
                        relayState.erase();
                    }
                    else {
                        relayState = out.string();
                        return;
                    }
                }
            }
        }
    }

    // Look for cookie-backed state of the form "cookie:key".
    if (strstr(state,"cookie:")==state) {
        state += 7;
        if (*state) {
            // Pull the value from the "relay state" cookie.
            pair<string,const char*> relay_cookie = application.getCookieNameProps("_shibstate_");
            relay_cookie.first = string("_shibstate_") + state;
            state = request.getCookie(relay_cookie.first.c_str());
            if (state && *state) {
                // URL-decode the value.
                char* rscopy=strdup(state);
                XMLToolingConfig::getConfig().getURLEncoder()->decode(rscopy);
                relayState = rscopy;
                free(rscopy);

                if (clear) {
                    string exp(relay_cookie.second);
                    exp += "; expires=Mon, 01 Jan 2001 00:00:00 GMT";
                    response.setCookie(relay_cookie.first.c_str(), exp.c_str());
                }
                return;
            }
        }

        relayState.erase();
    }

    // Check for "default" value (or the old "cookie" value that might come from stale bookmarks).
    if (relayState.empty() || relayState == "default" || relayState == "cookie") {
        pair<bool,const char*> homeURL=application.getString("homeURL");
        if (homeURL.first)
            relayState=homeURL.second;
        else {
            // Compute a URL to the root of the site.
            int port = request.getPort();
            const char* scheme = request.getScheme();
            relayState = string(scheme) + "://" + request.getHostname();
            if ((!strcmp(scheme,"http") && port!=80) || (!strcmp(scheme,"https") && port!=443)) {
                ostringstream portstr;
                portstr << port;
                relayState += ":" + portstr.str();
            }
            relayState += '/';
        }
    }
}