void ExtensibleAttribute::removeValue(size_t index)
{
    Attribute::removeValue(index);
    DDF vals = m_obj.first();
    if (index < static_cast<size_t>(vals.integer()))
        vals[static_cast<unsigned long>(index)].remove().destroy();
}
Example #2
0
XMLAttribute::XMLAttribute(DDF& in) : Attribute(in)
{
    DDF val = in.first().first();
    while (val.string()) {
        m_values.push_back(val.string());
        val = in.first().next();
    }
}
Example #3
0
DDF XMLAttribute::marshall() const
{
    DDF ddf = Attribute::marshall();
    ddf.name("XML");
    DDF vlist = ddf.first();
    for (vector<string>::const_iterator i=m_values.begin(); i!=m_values.end(); ++i)
        vlist.add(DDF(NULL).string(i->c_str()));
    return ddf;
}
Example #4
0
DDF DDF::getmember(const char* path) const
{
    char name[MAX_NAME_LEN+1];
    const char* path_ptr=path;
    DDF current;

    if (isstruct() && ddf_strlen(ddf_token(&path_ptr,name))>0) {
        current.m_handle=m_handle->value.children.first;
        while (current.m_handle && strcmp(current.m_handle->name,name)!=0)
            current.m_handle=current.m_handle->next;

        if (current.m_handle && ddf_strlen(path_ptr)>0)
            current=current.getmember(path_ptr);
    }
    return current;
}
void ListenerService::receive(DDF &in, ostream& out)
{
    if (!in.name())
        throw ListenerException("Incoming message with no destination address rejected.");
    else if (!strcmp("ping",in.name())) {
        DDF outmsg=DDF(NULL).integer(in.integer() + 1);
        DDFJanitor jan(outmsg);
        out << outmsg;
    }

    Locker locker(SPConfig::getConfig().getServiceProvider());
    Remoted* dest=lookup(in.name());
    if (!dest)
        throw ListenerException("No destination registered for incoming message addressed to ($1).",params(1,in.name()));
    
    dest->receive(in, out);
}
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();
}
pair<bool,long> AssertionConsumerService::finalizeResponse(
    const Application& application, const HTTPRequest& httpRequest, HTTPResponse& httpResponse, string& relayState
    ) const
{
    DDF postData = recoverPostData(application, httpRequest, httpResponse, relayState.c_str());
    DDFJanitor postjan(postData);
    recoverRelayState(application, httpRequest, httpResponse, relayState);
    application.limitRedirect(httpRequest, relayState.c_str());

    // Now redirect to the state value. By now, it should be set to *something* usable.
    // First check for POST data.
    if (!postData.islist()) {
        m_log.debug("ACS returning via redirect to: %s", relayState.c_str());
        return make_pair(true, httpResponse.sendRedirect(relayState.c_str()));
    }
    else {
        m_log.debug("ACS returning via POST to: %s", relayState.c_str());
        return make_pair(true, sendPostResponse(application, httpResponse, relayState.c_str(), postData));
    }
}
Example #8
0
void Application::clearAttributeHeaders(SPRequest& request) const
{
    if (SPConfig::getConfig().isEnabled(SPConfig::OutOfProcess)) {
        for (vector< pair<string,string> >::const_iterator i = m_unsetHeaders.begin(); i!=m_unsetHeaders.end(); ++i)
            request.clearHeader(i->first.c_str(), i->second.c_str());
        return;
    }

    m_lock->rdlock();
    if (m_unsetHeaders.empty()) {
        // No headers yet, so we have to request them from the remote half.
        m_lock->unlock();
        m_lock->wrlock();
        if (m_unsetHeaders.empty()) {
            SharedLock wrlock(m_lock, false);
            string addr=string(getId()) + "::getHeaders::Application";
            DDF out,in = DDF(addr.c_str());
            DDFJanitor jin(in),jout(out);
            out = getServiceProvider().getListenerService()->send(in);
            if (out.islist()) {
                DDF header = out.first();
                while (header.isstring()) {
                    m_unsetHeaders.push_back(pair<string,string>(header.name(),header.string()));
                    header = out.next();
                }
            }
        }
        else {
            m_lock->unlock();
        }
        m_lock->rdlock();
    }

    // Now holding read lock.
    SharedLock unsetLock(m_lock, false);
    for (vector< pair<string,string> >::const_iterator i = m_unsetHeaders.begin(); i!=m_unsetHeaders.end(); ++i)
        request.clearHeader(i->first.c_str(), i->second.c_str());
}
Example #9
0
DDF& DDF::empty()
{
    if (m_handle) {
        switch (m_handle->type) {
            case ddf_body_t::DDF_STRING:
                if (m_handle->value.string)
                    free(m_handle->value.string);
                break;
            case ddf_body_t::DDF_LIST:
            case ddf_body_t::DDF_STRUCT:
            {
                DDF temp;
                while (m_handle->value.children.first)
                {
                    temp.m_handle=m_handle->value.children.first;
                    temp.destroy();
                }
            }
        }
        m_handle->type=ddf_body_t::DDF_EMPTY;
    }
    return *this;
}
Example #10
0
void ListenerService::receive(DDF &in, ostream& out)
{
    if (!in.name())
        throw ListenerException("Incoming message with no destination address rejected.");
    else if (!strcmp("ping", in.name())) {
        DDF outmsg = DDF(nullptr).integer(in.integer() + 1);
        DDFJanitor jan(outmsg);
        out << outmsg;
        return;
    }
    else if (!strcmp("hash", in.name())) {
#ifndef SHIBSP_LITE
        const char* hashAlg = in["alg"].string();
        const char* data = in["data"].string();
        if (!hashAlg || !*hashAlg || !data || !*data)
            throw ListenerException("Hash request missing algorithm or data parameters.");
        DDF outmsg(nullptr);
        DDFJanitor jan(outmsg);
        outmsg.string(SecurityHelper::doHash(hashAlg, data, strlen(data)).c_str());
        out << outmsg;
        return;
#else
        throw ListenerException("Hash algorithms unavailable in lite build of library.");
#endif
    }

    // Two stage lookup, on the listener itself, and the SP interface.
    ServiceProvider* sp = SPConfig::getConfig().getServiceProvider();
    Locker locker(sp);
    Remoted* dest = lookup(in.name());
    if (!dest) {
        dest = sp->lookupListener(in.name());
        if (!dest)
            throw ListenerException("No destination registered for incoming message addressed to ($1).", params(1,in.name()));
    }

    dest->receive(in, out);
}
Example #11
0
void DDF::dump(FILE* f, int indent) const
{
    if (!f)
        f=stderr;

    ddf_print_indent(f,indent);
    if (m_handle) {
        switch (m_handle->type) {
            
            case ddf_body_t::DDF_EMPTY:
                fprintf(f,"empty");
                if (m_handle->name)
                    fprintf(f," %s",m_handle->name);
                break;

            case ddf_body_t::DDF_STRING:
                if (m_handle->name)
                    fprintf(f,"char* %s = ",m_handle->name);
                else
                    fprintf(f,"char* = ");
                if (const char* chptr=m_handle->value.string) {
                    putc('"',f);
                    while (*chptr)
                        fputc(*chptr++,f);
                    putc('"',f);
                }
                else
                    fprintf(f,"NULL");
                break;

            case ddf_body_t::DDF_INT:
                if (m_handle->name)
                    fprintf(f,"long %s = ",m_handle->name);
                else
                    fprintf(f,"long = ");
                fprintf(f,"%ld",m_handle->value.integer);
                break;

            case ddf_body_t::DDF_FLOAT:
                if (m_handle->name)
                    fprintf(f,"double %s = ",m_handle->name);
                else
                    fprintf(f,"double = ");
                fprintf(f,"%.15f",m_handle->value.floating);
                break;

            case ddf_body_t::DDF_STRUCT:
                fprintf(f,"struct ");
                if (m_handle->name)
                    fprintf(f,"%s ",m_handle->name);
                putc('{',f);
                if (m_handle->value.children.count) {
                    putc('\n',f);
                    DDF child;
                    child.m_handle=m_handle->value.children.first;
                    while (child.m_handle) {
                        child.dump(f,indent+2);
                        child.m_handle=child.m_handle->next;
                    }
                }
                ddf_print_indent(f,indent);
                putc('}',f);
                break;

            case ddf_body_t::DDF_LIST:
                fprintf(f,"list");
                if (m_handle->name)
                    fprintf(f," %s",m_handle->name);
                fprintf(f,"[%lu] {",m_handle->value.children.count);
                if (m_handle->value.children.count) {
                    putc('\n',f);
                    DDF child;
                    child.m_handle=m_handle->value.children.first;
                    while (child.m_handle) {
                        child.dump(f,indent+2);
                        child.m_handle=child.m_handle->next;
                    }
                }
                ddf_print_indent(f,indent);
                putc('}',f);
                break;

            case ddf_body_t::DDF_POINTER:
                if (m_handle->name)
                    fprintf(f,"void* %s = ",m_handle->name);
                else
                    fprintf(f,"void* = ");
                if (m_handle->value.pointer)
                    fprintf(f,"%p",m_handle->value.pointer);
                else
                    fprintf(f,"NULL");
                break;

            default:
                fprintf(f,"UNKNOWN -- WARNING: ILLEGAL VALUE");
        }
    }
    else
        fprintf(f,"NULL");
    fprintf(f,";\n");
}
Example #12
0
DDF SocketListener::send(const DDF& in)
{
#ifdef _DEBUG
    NDC ndc("send");
#endif

    log->debug("sending message (%s)", in.name() ? in.name() : "unnamed");

    // Serialize data for transmission.
    ostringstream os;
    os << in;
    string ostr(os.str());

    // Loop on the RPC in case we lost contact the first time through
#ifdef WIN32
    u_long len;
#else
    uint32_t len;
#endif
    int retry = 1;
    SocketListener::ShibSocket sock;
    while (retry >= 0) {
        sock = m_socketpool->get();
        
        int outlen = ostr.length();
        len = htonl(outlen);
        if (send(sock,(char*)&len,sizeof(len)) != sizeof(len) || send(sock,ostr.c_str(),outlen) != outlen) {
            log_error();
            this->close(sock);
            if (retry)
                retry--;
            else
                throw ListenerException("Failure sending remoted message ($1).", params(1,in.name()));
        }
        else {
            // SUCCESS.
            retry = -1;
        }
    }

    log->debug("send completed, reading response message");

    // Read the message.
    if (recv(sock,(char*)&len,sizeof(len)) != sizeof(len)) {
        log->error("error reading size of output message");
        this->close(sock);
        throw ListenerException("Failure receiving response to remoted message ($1).", params(1,in.name()));
    }
    len = ntohl(len);
    
    char buf[16384];
    int size_read;
    stringstream is;
    while (len && (size_read = recv(sock, buf, sizeof(buf))) > 0) {
        is.write(buf, size_read);
        len -= size_read;
    }
    
    if (len) {
        log->error("error reading output message from socket");
        this->close(sock);
        throw ListenerException("Failure receiving response to remoted message ($1).", params(1,in.name()));
    }
    
    m_socketpool->put(sock);

    // Unmarshall data.
    DDF out;
    is >> out;
    
    // Check for exception to unmarshall and throw, otherwise return.
    if (out.isstring() && out.name() && !strcmp(out.name(),"exception")) {
        // Reconstitute exception object.
        DDFJanitor jout(out);
        XMLToolingException* except=NULL;
        try { 
            except=XMLToolingException::fromString(out.string());
            log->error("remoted message returned an error: %s", except->what());
        }
        catch (XMLToolingException& e) {
            log->error("caught XMLToolingException while building the XMLToolingException: %s", e.what());
            log->error("XML was: %s", out.string());
            throw ListenerException("Remote call failed with an unparsable exception.");
        }

        auto_ptr<XMLToolingException> wrapper(except);
        wrapper->raise();
    }

    return out;
}
Example #13
0
 std::string getContentType() const {
     DDF s = m_input["content_type"];
     return s.string() ? s.string() : "";
 }
Example #14
0
 std::string getHeader(const char* name) const {
     DDF s = m_input["headers"][name];
     return s.string() ? s.string() : "";
 }
Example #15
0
 std::string getRemoteUser() const {
     DDF s = m_input["remote_user"];
     return s.string() ? s.string() : "";
 }
Example #16
0
 std::string getRemoteAddr() const {
     DDF s = m_input["client_addr"];
     return s.string() ? s.string() : "";
 }
Example #17
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));
    }
}
Example #18
0
ExtensibleAttribute::ExtensibleAttribute(DDF& in) : Attribute(in), m_obj(in.copy())
{
}
Example #19
0
int ServerThread::job()
{
    Category& log = Category::getInstance("shibd.Listener");

    bool incomingError = true;  // set false once incoming message is received
    ostringstream sink;
#ifdef WIN32
    u_long len;
#else
    uint32_t len;
#endif

    try {
        // Read the message.
        int readlength = m_listener->recv(m_sock,(char*)&len,sizeof(len));
        if (readlength == 0) {
            log.info("detected socket closure, shutting down worker thread");
            return 1;
        }
        else if (readlength != sizeof(len)) {
            log.error("error reading size of input message");
            return -1;
        }
        len = ntohl(len);
        
        int size_read;
        stringstream is;
        while (len && (size_read = m_listener->recv(m_sock, m_buf, sizeof(m_buf))) > 0) {
            is.write(m_buf, size_read);
            len -= size_read;
        }
        
        if (len) {
            log.error("error reading input message from socket");
            return -1;
        }
        
        // Unmarshall the message.
        DDF in;
        DDFJanitor jin(in);
        is >> in;

        log.debug("dispatching message (%s)", in.name() ? in.name() : "unnamed");

        incomingError = false;

        // Dispatch the message.
        m_listener->receive(in, sink);
    }
    catch (XMLToolingException& e) {
        if (incomingError)
            log.error("error processing incoming message: %s", e.what());
        DDF out=DDF("exception").string(e.toString().c_str());
        DDFJanitor jout(out);
        sink << out;
    }
    catch (exception& e) {
        if (incomingError)
            log.error("error processing incoming message: %s", e.what());
        ListenerException ex(e.what());
        DDF out=DDF("exception").string(ex.toString().c_str());
        DDFJanitor jout(out);
        sink << out;
    }
    catch (...) {
        if (incomingError)
            log.error("unexpected error processing incoming message");
        if (!m_listener->m_catchAll)
            throw;
        ListenerException ex("An unexpected error occurred while processing an incoming message.");
        DDF out=DDF("exception").string(ex.toString().c_str());
        DDFJanitor jout(out);
        sink << out;
    }
    
    // Return whatever's available.
    string response(sink.str());
    int outlen = response.length();
    len = htonl(outlen);
    if (m_listener->send(m_sock,(char*)&len,sizeof(len)) != sizeof(len)) {
        log.error("error sending output message size");
        return -1;
    }
    if (m_listener->send(m_sock,response.c_str(),outlen) != outlen) {
        log.error("error sending output message");
        return -1;
    }
    
    return 0;
}