Ejemplo n.º 1
0
void WebServer::onClientMessage(TcpClient* client, char* buffer, size_t size)
{
    clearExpiredSessions();

    HTTPResponse* resp = 0;
    HTTPRequest* req = new HTTPRequest(buffer,size);
    HTTPAuth auth = req->getAuthorization();
    bool authOK = validateAuthentication(req,auth);
    if (authOK)
    {
        if (mpListener!=0)
        {
            resp = mpListener->processHTTPRequest(req);
            if (resp!=0 && auth.nonce!="" && mSessions.find(auth.nonce)!=mSessions.end())
            {
                std::string cookie = "session="+auth.nonce;
                resp->setCookie(cookie);
            }
            sendResponse(resp,client);
        }
        else
        {
            resp = HTTPProtocol::buildBufferedResponse(ServiceUnavailable,"","");
            sendResponse(resp,client);
        }
    }
    else
    {
        std::string nonce = "";
        WebSession ws;
        if (auth.nonce!="" && mSessions.find(auth.nonce) != mSessions.end())
        {
            nonce = auth.nonce;
            ws = mSessions[nonce];
        }
        else
        {
            nonce = generateNonce();
            ws.mNonce = nonce;
        }

        time_t t;
        time(&t);
        t+=mSessionExpires;
        ws.mExpires = t;
        mSessions[nonce] = ws;
        std::string content = "{\"status\" : \"Authorization needed\"}";
        std::string authHeader = "Digest realm=\"dumais\",nonce=\""+nonce+"\"";
        HTTPResponseCode code = Unauthorized;
        resp = HTTPProtocol::buildBufferedResponse(code,content,"application/json", authHeader);
        if (req->wantsAuthenticationHack()) resp->useAuthenticationHack();
        sendResponse(resp,client);
    }

    delete buffer;
}
Ejemplo n.º 2
0
DDF AbstractHandler::recoverPostData(
    const Application& application, const HTTPRequest& request, HTTPResponse& response, const char* relayState
    ) const
{
    // First we need the post recovery cookie.
    pair<string,const char*> shib_cookie = getPostCookieNameProps(application, relayState);
    const char* cookie = request.getCookie(shib_cookie.first.c_str());
    if (!cookie || !*cookie)
        return DDF();

    // Clear the cookie.
    string exp(shib_cookie.second);
    exp += "; expires=Mon, 01 Jan 2001 00:00:00 GMT";
    response.setCookie(shib_cookie.first.c_str(), exp.c_str());

    // Look for StorageService-backed state of the form "ss:SSID:key".
    const char* state = cookie;
    if (strstr(state, "ss:") == state) {
        state += 3;
        const char* key = strchr(state, ':');
        if (key) {
            string ssid = string(cookie).substr(3, key - state);
            key++;
            if (!ssid.empty() && *key) {
                SPConfig& conf = SPConfig::getConfig();
                if (conf.isEnabled(SPConfig::OutOfProcess)) {
#ifndef SHIBSP_LITE
                    StorageService* storage = conf.getServiceProvider()->getStorageService(ssid.c_str());
                    if (storage) {
                        if (storage->readString("PostData", key, &ssid) > 0) {
                            storage->deleteString("PostData", key);
                            istringstream inret(ssid);
                            DDF ret;
                            inret >> ret;
                            return ret;
                        }
                        else {
                            m_log.error("failed to recover form post data using key (%s)", key);
                        }
                    }
Ejemplo n.º 3
0
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));
    }
}
Ejemplo n.º 4
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 += '/';
        }
    }
}
Ejemplo n.º 5
0
void AbstractHandler::preserveRelayState(const Application& application, HTTPResponse& response, string& relayState) const
{
    if (relayState.empty())
        return;

    // No setting means just pass it by value.
    pair<bool,const char*> mech=getString("relayState");
    if (!mech.first || !mech.second || !*mech.second)
        return;

    if (!strcmp(mech.second, "cookie")) {
        // Here we store the state in a cookie and send a fixed
        // value so we can recognize it on the way back.
        if (relayState.find("cookie:") != 0) {
            const URLEncoder* urlenc = XMLToolingConfig::getConfig().getURLEncoder();
            pair<string,const char*> shib_cookie=application.getCookieNameProps("_shibstate_");
            string stateval = urlenc->encode(relayState.c_str()) + shib_cookie.second;
            // Generate a random key for the cookie name instead of the fixed name.
            string rsKey;
            generateRandomHex(rsKey,5);
            shib_cookie.first = "_shibstate_" + rsKey;
            response.setCookie(shib_cookie.first.c_str(),stateval.c_str());
            relayState = "cookie:" + rsKey;
        }
    }
    else if (strstr(mech.second,"ss:")==mech.second) {
        if (relayState.find("ss:") != 0) {
            mech.second+=3;
            if (*mech.second) {
                if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
#ifndef SHIBSP_LITE
                    StorageService* storage = application.getServiceProvider().getStorageService(mech.second);
                    if (storage) {
                        string rsKey;
                        generateRandomHex(rsKey,5);
                        if (!storage->createString("RelayState", rsKey.c_str(), relayState.c_str(), time(NULL) + 600))
                            throw IOException("Attempted to insert duplicate storage key.");
                        relayState = string(mech.second-3) + ':' + rsKey;
                    }
                    else {
                        m_log.error("Storage-backed RelayState with invalid StorageService ID (%s)", mech.second);
                        relayState.erase();
                    }
#endif
                }
                else if (SPConfig::getConfig().isEnabled(SPConfig::InProcess)) {
                    DDF out,in = DDF("set::RelayState").structure();
                    in.addmember("id").string(mech.second);
                    in.addmember("value").unsafe_string(relayState.c_str());
                    DDFJanitor jin(in),jout(out);
                    out = application.getServiceProvider().getListenerService()->send(in);
                    if (!out.isstring())
                        throw IOException("StorageService-backed RelayState mechanism did not return a state key.");
                    relayState = string(mech.second-3) + ':' + out.string();
                }
            }
        }
    }
    else
        throw ConfigurationException("Unsupported relayState mechanism ($1).", params(1,mech.second));
}
void LoginHTTPRequestHandler::createResponse(const HTTPRequest &r)
{
    HTTPResponse response;
    QString page = "\r\n<html><body>"
            "<form method=\"POST\">"
            "%1"
            "Username: <input type=\"text\" name=\"username\">"
            "Password: <input type=\"password\" name=\"pass\">"
            "<INPUT type=\"submit\" value=\"Auth\">"
            "</form></body></html>";

    if("GET" == r.method){
        response.setStatusCode(200);
        response.setReasonPhrase("OK");

        QList<QNetworkCookie> cookieList = QtConcurrent::blockingFiltered(r.cookieJar,
            [] (const QNetworkCookie &cookie) -> bool {
                return cookie.name() == "loggedin" &&  cookie.value() == "1";
            }
        );

        if(1 == cookieList.size()){
            response.setBody("You're logged in!");
        }
        else{
            response.setBody(page.arg(""));
        }

        emit responseWritten(response);
        emit endOfWriting();
        return;
    }

    if("POST" == r.method && !r.postData.isEmpty()){
        if(r.postData.contains("username") &&
                "Ion" == r.postData["username"] &&
                r.postData.contains("pass") &&
                "1234" == r.postData["pass"]){

            response.setStatusCode(200);
            response.setReasonPhrase("OK");

            //TODO: this could be something randomized in order to avoid replicating
            QNetworkCookie cookie("loggedin", "1");
            cookie.setHttpOnly(true);
            response.setCookie(cookie);

            response.setBody("You're logged in!\n");

            emit responseWritten(response);
            emit endOfWriting();
            return;
        }

        response.setStatusCode(200);
        response.setReasonPhrase("OK");
        response.setBody(page.arg("Login failed, try again!<br>"));

        emit responseWritten(response);
        emit endOfWriting();
        return;
    }


    response.setStatusCode(400);
    response.setReasonPhrase("Bad request");

    emit responseWritten(response);
    emit endOfWriting();
}