void Sasl::respond(qpid::SaslServer::Status status, const std::string& chllnge) { switch (status) { case qpid::SaslServer::OK: connection.setUserid(authenticator->getUserid()); completed(true); //can't set authenticated & failed until we have actually sent the outcome state = SUCCESS_PENDING; securityLayer = authenticator->getSecurityLayer(65535); if (securityLayer.get()) { QPID_LOG_CAT(info, security, id << " Security layer installed"); securityLayer->init(&connection); connection.setSaslSsf(securityLayer->getSsf()); } QPID_LOG_CAT(info, security, id << " Authenticated as " << authenticator->getUserid()); break; case qpid::SaslServer::FAIL: completed(false); state = FAILURE_PENDING; QPID_LOG_CAT(info, security, id << " Failed to authenticate"); break; case qpid::SaslServer::CHALLENGE: challenge(&chllnge); QPID_LOG_CAT(info, security, id << " Challenge issued"); break; } haveOutput = true; out.activateOutput(); }
std::size_t ConnectionContext::encode(char* buffer, std::size_t size) { qpid::sys::ScopedLock<qpid::sys::Monitor> l(lock); QPID_LOG(trace, id << " encode(" << size << ")"); if (writeHeader) { size_t encoded = writeProtocolHeader(buffer, size); if (encoded < size) { encoded += encode(buffer + encoded, size - encoded); } return encoded; } ssize_t n = pn_transport_output(engine, buffer, size); if (n > 0) { QPID_LOG_CAT(debug, network, id << " encoded " << n << " bytes from " << size) haveOutput = true; return n; } else if (n == PN_ERR) { throw qpid::Exception(QPID_MSG("Error on output: " << getError())); } else if (n == PN_EOS) { haveOutput = false; return 0;//Is this right? } else { haveOutput = false; return 0; } }
std::size_t ConnectionContext::decode(const char* buffer, std::size_t size) { qpid::sys::ScopedLock<qpid::sys::Monitor> l(lock); QPID_LOG(trace, id << " decode(" << size << ")"); if (readHeader) { size_t decoded = readProtocolHeader(buffer, size); if (decoded < size) { decoded += decode(buffer + decoded, size - decoded); } return decoded; } //TODO: Fix pn_engine_input() to take const buffer ssize_t n = pn_transport_input(engine, const_cast<char*>(buffer), size); if (n > 0 || n == PN_EOS) { //If engine returns EOS, have no way of knowing how many bytes //it processed, but can assume none need to be reprocessed so //consider them all read: if (n == PN_EOS) n = size; QPID_LOG_CAT(debug, network, id << " decoded " << n << " bytes from " << size) pn_transport_tick(engine, 0); lock.notifyAll(); return n; } else if (n == PN_ERR) { throw qpid::Exception(QPID_MSG("Error on input: " << getError())); } else { return 0; } }
void Sasl::init(const std::string& mechanism, const std::string* response, const std::string* /*hostname*/) { QPID_LOG_CAT(debug, protocol, id << " Received SASL-INIT(" << mechanism << ", " << (response ? *response : EMPTY) << ")"); //TODO: what should we do with hostname here? std::string c; respond(authenticator->start(mechanism, response, c), c); connection.setSaslMechanism(mechanism); }
void SaslServer::completed(bool succeeded) { void* frameToken = startFrame(); void* listToken = encoder.startList8(&SASL_OUTCOME); encoder.writeUByte(succeeded ? 0 : 1); encoder.endList8(1, listToken); endFrame(frameToken); QPID_LOG_CAT(debug, protocol, id << " Sent SASL-OUTCOME(" << (succeeded ? 0 : 1) << ") " << encoder.getPosition()); }
void SaslServer::challenge(const std::string* c) { void* frameToken = startFrame(); void* listToken = encoder.startList32(&SASL_CHALLENGE); if (c) encoder.writeBinary(*c); else encoder.writeNull(); encoder.endList32(1, listToken); endFrame(frameToken); QPID_LOG_CAT(debug, protocol, id << " Sent SASL-CHALLENGE(" << (c ? *c : NULL_) << ") " << encoder.getPosition()); }
void SaslClient::response(const std::string* r) { void* frame = startFrame(); void* token = encoder.startList32(&SASL_RESPONSE); if (r) encoder.writeBinary(*r); else encoder.writeNull(); encoder.endList32(1, token); endFrame(frame); QPID_LOG_CAT(debug, protocol, id << " Sent SASL-RESPONSE(" << (r ? *r : "null") << ")"); }
std::size_t ConnectionContext::readProtocolHeader(const char* buffer, std::size_t size) { framing::ProtocolInitiation pi(getVersion()); if (size >= pi.encodedSize()) { readHeader = false; qpid::framing::Buffer out(const_cast<char*>(buffer), size); pi.decode(out); QPID_LOG_CAT(debug, protocol, id << " read protocol header: " << pi); return pi.encodedSize(); } else { return 0; } }
std::size_t ConnectionContext::writeProtocolHeader(char* buffer, std::size_t size) { framing::ProtocolInitiation pi(getVersion()); if (size >= pi.encodedSize()) { QPID_LOG_CAT(debug, protocol, id << " writing protocol header: " << pi); writeHeader = false; qpid::framing::Buffer out(buffer, size); pi.encode(out); return pi.encodedSize(); } else { QPID_LOG_CAT(debug, protocol, id << " insufficient buffer for protocol header: " << size) return 0; } }
void SaslClient::init(const std::string& mechanism, const std::string* response, const std::string* hostname) { void* frame = startFrame(); void* token = encoder.startList32(&SASL_INIT); encoder.writeSymbol(mechanism); if (response) encoder.writeBinary(*response); else encoder.writeNull(); if (hostname) encoder.writeString(*hostname); else encoder.writeNull(); encoder.endList32(3, token); endFrame(frame); QPID_LOG_CAT(debug, protocol, id << " Sent SASL-INIT(" << mechanism << ", " << (response ? *response : "null") << ", " << (hostname ? *hostname : "null") << ")"); }
void Interconnect::process() { QPID_LOG(trace, id << " processing interconnect"); if (closeRequested) { close(); } else { if ((pn_connection_state(connection) & UNINIT) == UNINIT) { QPID_LOG_CAT(debug, model, id << " interconnect open initiated"); pn_connection_set_container(connection, getBroker().getFederationTag().c_str()); setProperties(connection); pn_connection_open(connection); out.connectionEstablished(); setInterconnectDomain(domain); } if (!isOpened && (pn_connection_state(connection) & PN_REMOTE_ACTIVE)) { QPID_LOG_CAT(debug, model, id << " interconnect open completed, attaching link"); isOpened = true; readPeerProperties(); const char* containerid(pn_connection_remote_container(connection)); if (containerid) { setContainerId(std::string(containerid)); } opened(); getBroker().getConnectionObservers().opened(*this); pn_session_t* s = pn_session(connection); pn_session_open(s); boost::shared_ptr<Session> ssn(new Session(s, *this, out)); sessions[s] = ssn; pn_link_t* l = incoming ? pn_receiver(s, name.c_str()) : pn_sender(s, name.c_str()); pn_link_open(l); ssn->attach(l, source, target, relay); } Connection::process(); } }
void SaslServer::mechanisms(const std::string& mechanisms) { void* frameToken = startFrame(); std::vector<std::string> parts = split(mechanisms, SPACE); void* listToken = encoder.startList32(&SASL_MECHANISMS); if (parts.size() > 1) { void* arrayToken = encoder.startArray8(Constructor(SYMBOL8)); for (std::vector<std::string>::const_iterator i = parts.begin();i != parts.end(); ++i) { uint8_t size = i->size() > std::numeric_limits<uint8_t>::max() ? std::numeric_limits<uint8_t>::max() : i->size(); encoder.write(size); encoder.writeBytes(i->data(), size); } encoder.endArray8(parts.size(), arrayToken); } else { encoder.writeSymbol(mechanisms); } encoder.endList32(1, listToken); endFrame(frameToken); QPID_LOG_CAT(debug, protocol, id << " Sent SASL-MECHANISMS(" << mechanisms << ") " << encoder.getPosition()); }
void Connection::process() { QPID_LOG(trace, id << " process()"); if ((pn_connection_state(connection) & REQUIRES_OPEN) == REQUIRES_OPEN) { QPID_LOG_CAT(debug, model, id << " connection opened"); pn_connection_set_container(connection, broker.getFederationTag().c_str()); pn_connection_open(connection); } for (pn_session_t* s = pn_session_head(connection, REQUIRES_OPEN); s; s = pn_session_next(s, REQUIRES_OPEN)) { QPID_LOG_CAT(debug, model, id << " session begun"); pn_session_open(s); boost::shared_ptr<Session> ssn(new Session(s, broker, *this, out)); sessions[s] = ssn; } for (pn_link_t* l = pn_link_head(connection, REQUIRES_OPEN); l; l = pn_link_next(l, REQUIRES_OPEN)) { pn_link_open(l); Sessions::iterator session = sessions.find(pn_link_session(l)); if (session == sessions.end()) { QPID_LOG(error, id << " Link attached on unknown session!"); } else { try { session->second->attach(l); QPID_LOG_CAT(debug, protocol, id << " link " << l << " attached on " << pn_link_session(l)); } catch (const std::exception& e) { QPID_LOG_CAT(error, protocol, "Error on attach: " << e.what()); //TODO: set error details on detach when that is exposed via engine API pn_link_close(l); } } } //handle deliveries for (pn_delivery_t* delivery = pn_work_head(connection); delivery; delivery = pn_work_next(delivery)) { pn_link_t* link = pn_delivery_link(delivery); if (pn_link_is_receiver(link)) { Sessions::iterator i = sessions.find(pn_link_session(link)); if (i != sessions.end()) { i->second->readable(link, delivery); } else { pn_delivery_update(delivery, PN_REJECTED); } } else { //i.e. SENDER Sessions::iterator i = sessions.find(pn_link_session(link)); if (i != sessions.end()) { QPID_LOG(trace, id << " handling outgoing delivery for " << link << " on session " << pn_link_session(link)); i->second->writable(link, delivery); } else { QPID_LOG(error, id << " Got delivery for non-existent session: " << pn_link_session(link) << ", link: " << link); } } } for (pn_link_t* l = pn_link_head(connection, REQUIRES_CLOSE); l; l = pn_link_next(l, REQUIRES_CLOSE)) { pn_link_close(l); Sessions::iterator session = sessions.find(pn_link_session(l)); if (session == sessions.end()) { QPID_LOG(error, id << " peer attempted to detach link on unknown session!"); } else { session->second->detach(l); QPID_LOG_CAT(debug, model, id << " link detached"); } } for (pn_session_t* s = pn_session_head(connection, REQUIRES_CLOSE); s; s = pn_session_next(s, REQUIRES_CLOSE)) { pn_session_close(s); Sessions::iterator i = sessions.find(s); if (i != sessions.end()) { i->second->close(); sessions.erase(i); QPID_LOG_CAT(debug, model, id << " session ended"); } else { QPID_LOG(error, id << " peer attempted to close unrecognised session"); } } if ((pn_connection_state(connection) & REQUIRES_CLOSE) == REQUIRES_CLOSE) { QPID_LOG_CAT(debug, model, id << " connection closed"); pn_connection_close(connection); } }
void Sasl::response(const std::string* r) { QPID_LOG_CAT(debug, protocol, id << " Received SASL-RESPONSE(" << (r ? *r : EMPTY) << ")"); std::string c; respond(authenticator->step(r, c), c); }