Пример #1
0
 krb5_error_code smb_krb5_get_keyinfo_from_ap_req(krb5_context context, 
						 const krb5_data *inbuf, 
						 krb5_kvno *kvno, 
						 krb5_enctype *enctype)
{
	krb5_error_code ret;
#ifdef HAVE_KRB5_DECODE_AP_REQ /* Heimdal */
	{
		krb5_ap_req ap_req;
		
		ret = krb5_decode_ap_req(context, inbuf, &ap_req);
		if (ret)
			return ret;

		*kvno = get_kvno_from_ap_req(&ap_req);
		*enctype = get_enctype_from_ap_req(&ap_req);

		smb_krb5_free_ap_req(context, &ap_req);
	}
#elif defined(HAVE_DECODE_KRB5_AP_REQ) /* MIT */
	{
		krb5_ap_req *ap_req = NULL;

		ret = decode_krb5_ap_req(inbuf, &ap_req);
		if (ret)
			return ret;
		
		*kvno = get_kvno_from_ap_req(ap_req);
		*enctype = get_enctype_from_ap_req(ap_req);

		smb_krb5_free_ap_req(context, ap_req);
	}
#else
#error UNKOWN_KRB5_AP_REQ_DECODING_FUNCTION
#endif
	return ret;
}
Пример #2
0
void DecryptionManager::PacketHandler::parseFirstMessage(Packet* packet) {
  // Parse input token from thrift request.
  unique_ptr<IOBuf> msg = removeThriftHeader(packet);
  if (!msg) {
    return;
  }

  apache::thrift::sasl::SaslStart saslStart;
  apache::thrift::sasl::SaslAuthService_authFirstRequest_pargs pargs;
  pargs.saslStart = &saslStart;

  try {
    std::string methodName;
    try {
     methodName = PargsPresultProtoDeserialize(
          header_->getProtocolId(),
          pargs,
          msg.get(),
          T_CALL).first;
    } catch (const TProtocolException& e) {
      if (header_->getProtocolId() == protocol::T_BINARY_PROTOCOL &&
          e.getType() == TProtocolException::BAD_VERSION) {
        methodName = PargsPresultProtoDeserialize(
            protocol::T_COMPACT_PROTOCOL,
            pargs,
            msg.get(),
            T_CALL).first;
      } else {
        onError("Protocol mismatch parsing first thrift security message");
        return;
      }
    }
    if (methodName != "authFirstRequest") {
      onError("Bad first auth request. Maybe not secure thrift connection?");
      return;
    }
  } catch(...) {
    onError("Caught exception parsing first thrift security message");
  }

  std::string authReq = saslStart.request.response;

  // Parse encrypted authenticator from input token. This is mostly
  // copied from accept_sec_context.c.
  gss_buffer_desc inputToken;
  inputToken.length = authReq.length();
  inputToken.value = (void*)authReq.data();
  krb5_data ap_req;
  krb5_error_code code;
  unsigned char *ptr;
  char *sptr;
  krb5_ap_req *request = nullptr;

  ptr = (unsigned char*) inputToken.value;
  code = gssint_g_verify_token_header(gss_mech_krb5, // always use krb5
                                      &(ap_req.length),
                                      &ptr,
                                      KG_TOK_CTX_AP_REQ,
                                      inputToken.length, 1);
  if (code) {
    onError("Failed to verify ap_req input token header");
    return;
  }


  sptr = (char*) ptr;
  TREAD_STR(sptr, ap_req.data, ap_req.length);

  code = decode_krb5_ap_req(&ap_req, &request);
  if (code) {
    onError("Cannot decode ap_req");
    return;
  }

  readServiceSessionKey(request->ticket);
  if (!sessionKey_ || sessionKey_->length == 0) {
    onError("Failed to read session key");
    return;
  }

  krb5_data scratch;
  scratch.length = request->authenticator.ciphertext.length;
  scratch.data = (char*)malloc(scratch.length);
  if (!scratch.data) {
    throw std::runtime_error("Cannot allocate memory");
  }

  SCOPE_EXIT {
    memset(scratch.data, 0, scratch.length);
    free(scratch.data);
  };

  code = krb5_c_decrypt(ctx_->get(),
                        sessionKey_,
                        KRB5_KEYUSAGE_AP_REQ_AUTH,
                        0,
                        &request->authenticator,
                        &scratch);
  if (code) {
    onError("Cannot decrypt authenticator");
    return;
  }

  krb5_authenticator *authenticator;
  code = decode_krb5_authenticator(&scratch, &authenticator);
  if (code) {
    onError("Cannot decode authenticator");
    return;
  }

  SCOPE_EXIT {
    free(authenticator);
  };

  // Store this subsession key. In the current thrift security
  // implementation this subkey is always present and server
  // uses it to generate another subkey, which will be used for
  // encrypt/decrypt application messages.
  if (authenticator->subkey) {
    krb5_copy_keyblock(ctx_->get(), authenticator->subkey, &subkey_);
  }
}