void TSaslTransport::open() { NegotiationStatus status = TSASL_INVALID; uint32_t resLength; // Only client should open the underlying transport. if (isClient_ && !transport_->isOpen()) { transport_->open(); } // initiate SASL message handleSaslStartMessage(); // SASL connection handshake while (!sasl_->isComplete()) { uint8_t* message = receiveSaslMessage(&status, &resLength); if (status == TSASL_COMPLETE) { if (isClient_) { if (!sasl_->isComplete()) { // Server sent COMPLETE out of order. throw TTransportException("Received COMPLETE but no handshake occurred"); } break; // handshake complete } } else if (status != TSASL_OK) { stringstream ss; ss << "Expected COMPLETE or OK, got " << status; throw TTransportException(ss.str()); } uint32_t challengeLength; uint8_t* challenge = sasl_->evaluateChallengeOrResponse( message, resLength, &challengeLength); sendSaslMessage(sasl_->isComplete() ? TSASL_COMPLETE : TSASL_OK, challenge, challengeLength); } // If the server isn't complete yet, we need to wait for its response. // This will occur with ANONYMOUS auth, for example, where we send an // initial response and are immediately complete. if (isClient_ && (status == TSASL_INVALID || status == TSASL_OK)) { receiveSaslMessage(&status, &resLength); if (status != TSASL_COMPLETE) { stringstream ss; ss << "Expected COMPLETE or OK, got " << status; throw TTransportException(ss.str()); } } // TODO : need to set the shouldWrap_ based on QOP /* String qop = (String) sasl.getNegotiatedProperty(Sasl.QOP); if (qop != null && !qop.equalsIgnoreCase("auth")) shouldWrap_ = true; */ }
void TSaslTransport::open() { // Only client should open the underlying transport. if (isClient_ && !transport_->isOpen()) transport_->open(); // initiate SASL message handleSaslStartMessage(); // The number of messages received so far. int numMessagesReceived = 0; NegotiationStatus status = TSASL_INVALID; uint32_t msgLength; // SASL connection handshake while (!sasl_->isComplete()) { uint8_t* message = receiveSaslMessage(&status, &msgLength); ++numMessagesReceived; if (status != TSASL_COMPLETE && status != TSASL_OK) { stringstream ss; ss << "Expected COMPLETE or OK, got " << status; throw TTransportException(ss.str()); } if (numMessagesReceived == 1 && msgLength == 0 && sasl_->getMechanismName() == "DIGEST-MD5") { // TODO: this is a hack, not sure what the proper behavior is. These messages // are optional and checking for QOP support. // What's the general way to implement the protocol? continue; } uint32_t challengeLength; uint8_t* challenge = sasl_->evaluateChallengeOrResponse( message, msgLength, &challengeLength); if (status == TSASL_COMPLETE && isClient_) { // If we are the client, and the server indicates COMPLETE, we don't need to // send back any further response. break; } sendSaslMessage(sasl_->isComplete() ? TSASL_COMPLETE : TSASL_OK, challenge, challengeLength); } // If the server isn't complete yet, we need to wait for its response. // This will occur with ANONYMOUS auth, for example, where we send an // initial response and are immediately complete. if (isClient_ && (status == TSASL_INVALID || status == TSASL_OK)) { receiveSaslMessage(&status, &msgLength); if (status != TSASL_COMPLETE) { stringstream ss; ss << "Expected COMPLETE or OK, got " << status; throw TTransportException(ss.str()); } } // TODO : need to set the shouldWrap_ based on QOP /* String qop = (String) sasl.getNegotiatedProperty(Sasl.QOP); if (qop != null && !qop.equalsIgnoreCase("auth")) shouldWrap_ = true; */ }