Пример #1
0
krb5_error_code KRB5_CALLCONV
krb5_rd_rep_dce(krb5_context context, krb5_auth_context auth_context,
                const krb5_data *inbuf, krb5_ui_4 *nonce)
{
    krb5_error_code       retval;
    krb5_ap_rep         * reply;
    krb5_data             scratch;
    krb5_ap_rep_enc_part *repl = NULL;

    if (!krb5_is_ap_rep(inbuf))
        return KRB5KRB_AP_ERR_MSG_TYPE;

    /* decode it */

    if ((retval = decode_krb5_ap_rep(inbuf, &reply)))
        return retval;

    /* put together an eblock for this encryption */

    scratch.length = reply->enc_part.ciphertext.length;
    if (!(scratch.data = malloc(scratch.length))) {
        krb5_free_ap_rep(context, reply);
        return(ENOMEM);
    }

    if ((retval = krb5_k_decrypt(context, auth_context->key,
                                 KRB5_KEYUSAGE_AP_REP_ENCPART, 0,
                                 &reply->enc_part, &scratch)))
        goto clean_scratch;

    /* now decode the decrypted stuff */
    retval = decode_krb5_ap_rep_enc_part(&scratch, &repl);
    if (retval)
        goto clean_scratch;

    *nonce = repl->seq_number;
    if (*nonce != auth_context->local_seq_number) {
        retval = KRB5_MUTUAL_FAILED;
        goto clean_scratch;
    }

    /* Must be NULL to prevent echoing for client AP-REP */
    if (repl->subkey != NULL) {
        retval = KRB5_MUTUAL_FAILED;
        goto clean_scratch;
    }

    TRACE_RD_REP_DCE(context, repl->ctime, repl->cusec, repl->seq_number);

clean_scratch:
    memset(scratch.data, 0, scratch.length);

    if (repl != NULL)
        krb5_free_ap_rep_enc_part(context, repl);
    krb5_free_ap_rep(context, reply);
    free(scratch.data);
    return retval;
}
Пример #2
0
krb5_error_code KRB5_CALLCONV
krb5_rd_rep(krb5_context context, krb5_auth_context auth_context,
	    const krb5_data *inbuf, krb5_ap_rep_enc_part **repl)
{
    krb5_error_code 	  retval;
    krb5_ap_rep 	* reply;
    krb5_data 	 	  scratch;

    if (!krb5_is_ap_rep(inbuf))
	return KRB5KRB_AP_ERR_MSG_TYPE;

    /* decode it */

    if ((retval = decode_krb5_ap_rep(inbuf, &reply)))
	return retval;

    /* put together an eblock for this encryption */

    scratch.length = reply->enc_part.ciphertext.length;
    if (!(scratch.data = malloc(scratch.length))) {
	krb5_free_ap_rep(context, reply);
	return(ENOMEM);
    }

    if ((retval = krb5_c_decrypt(context, auth_context->keyblock,
				 KRB5_KEYUSAGE_AP_REP_ENCPART, 0,
				 &reply->enc_part, &scratch)))
	goto clean_scratch;

    /* now decode the decrypted stuff */
    retval = decode_krb5_ap_rep_enc_part(&scratch, repl);
    if (retval)
	goto clean_scratch;

    /* Check reply fields */
    if (((*repl)->ctime != auth_context->authentp->ctime) ||
      ((*repl)->cusec != auth_context->authentp->cusec)) {
	retval = KRB5_MUTUAL_FAILED;
	goto clean_scratch;
    }

    /* Set auth subkey */
    if ((*repl)->subkey) {
	if (auth_context->recv_subkey) {
	    krb5_free_keyblock(context, auth_context->recv_subkey);
	    auth_context->recv_subkey = NULL;
	}
	retval = krb5_copy_keyblock(context, (*repl)->subkey,
				    &auth_context->recv_subkey);
	if (retval)
	    goto clean_scratch;
	if (auth_context->send_subkey) {
	    krb5_free_keyblock(context, auth_context->send_subkey);
	    auth_context->send_subkey = NULL;
	}
	retval = krb5_copy_keyblock(context, (*repl)->subkey,
				    &auth_context->send_subkey);
	if (retval) {
	    krb5_free_keyblock(context, auth_context->send_subkey);
	    auth_context->send_subkey = NULL;
	}
	/* not used for anything yet */
	auth_context->negotiated_etype = (*repl)->subkey->enctype;
    }

    /* Get remote sequence number */
    auth_context->remote_seq_number = (*repl)->seq_number;

clean_scratch:
    memset(scratch.data, 0, scratch.length); 

    krb5_free_ap_rep(context, reply);
    free(scratch.data);
    return retval;
}
Пример #3
0
krb5_error_code KRB5_CALLCONV
krb5_rd_rep(krb5_context context, krb5_auth_context auth_context,
            const krb5_data *inbuf, krb5_ap_rep_enc_part **repl)
{
    krb5_error_code       retval;
    krb5_ap_rep          *reply = NULL;
    krb5_ap_rep_enc_part *enc = NULL;
    krb5_data             scratch;

    *repl = NULL;

    if (!krb5_is_ap_rep(inbuf))
        return KRB5KRB_AP_ERR_MSG_TYPE;

    /* Decode inbuf. */
    retval = decode_krb5_ap_rep(inbuf, &reply);
    if (retval)
        return retval;

    /* Put together an eblock for this encryption. */
    scratch.length = reply->enc_part.ciphertext.length;
    scratch.data = malloc(scratch.length);
    if (scratch.data == NULL) {
        retval = ENOMEM;
        goto clean_scratch;
    }

    retval = krb5_k_decrypt(context, auth_context->key,
                            KRB5_KEYUSAGE_AP_REP_ENCPART, 0,
                            &reply->enc_part, &scratch);
    if (retval)
        goto clean_scratch;

    /* Now decode the decrypted stuff. */
    retval = decode_krb5_ap_rep_enc_part(&scratch, &enc);
    if (retval)
        goto clean_scratch;

    /* Check reply fields. */
    if ((enc->ctime != auth_context->authentp->ctime)
        || (enc->cusec != auth_context->authentp->cusec)) {
        retval = KRB5_MUTUAL_FAILED;
        goto clean_scratch;
    }

    /* Set auth subkey. */
    if (enc->subkey) {
        retval = krb5_auth_con_setrecvsubkey(context, auth_context,
                                             enc->subkey);
        if (retval)
            goto clean_scratch;
        retval = krb5_auth_con_setsendsubkey(context, auth_context,
                                             enc->subkey);
        if (retval) {
            (void) krb5_auth_con_setrecvsubkey(context, auth_context, NULL);
            goto clean_scratch;
        }
        /* Not used for anything yet. */
        auth_context->negotiated_etype = enc->subkey->enctype;
    }

    /* Get remote sequence number. */
    auth_context->remote_seq_number = enc->seq_number;

    TRACE_RD_REP(context, enc->ctime, enc->cusec, enc->subkey,
                 enc->seq_number);

    *repl = enc;
    enc = NULL;

clean_scratch:
    if (scratch.data)
        memset(scratch.data, 0, scratch.length);
    free(scratch.data);
    krb5_free_ap_rep(context, reply);
    krb5_free_ap_rep_enc_part(context, enc);
    return retval;
}
Пример #4
0
void DecryptionManager::PacketHandler::parseSecondMessage(Packet* packet) {
  // Parse input token from thrift response.
  unique_ptr<IOBuf> msg = removeThriftHeader(packet);
  if (!msg) {
    return;
  }

  apache::thrift::sasl::SaslReply saslReply;
  apache::thrift::sasl::SaslAuthService_authFirstRequest_presult presult;
  presult.success = &saslReply;

  std::string methodName;
  try {
   methodName = PargsPresultProtoDeserialize(
        header_->getProtocolId(),
        presult,
        msg.get(),
        T_REPLY).first;
  } catch (const TProtocolException& e) {
    if (header_->getProtocolId() == protocol::T_BINARY_PROTOCOL &&
        e.getType() == TProtocolException::BAD_VERSION) {
      methodName = PargsPresultProtoDeserialize(
          protocol::T_COMPACT_PROTOCOL,
          presult,
          msg.get(),
          T_REPLY).first;
    } else {
      onError("Cannot parse second thrift security negotiation message");
      return;
    }
  }

  if (methodName != "authFirstRequest") {
    onError("Bad auth first reply");
    return;
  }
  std::string authRep = saslReply.challenge;

  // Parse encrypted APP_REP from input token. This is mostly
  // copied from init_sec_context.c.
  gss_buffer_desc inputToken;
  inputToken.length = authRep.length();
  inputToken.value = (void*)authRep.data();
  krb5_data ap_rep;
  unsigned char *ptr;
  char *sptr;
  krb5_ap_rep *reply = nullptr;
  krb5_ap_rep_enc_part *enc = nullptr;
  krb5_error_code code;

  ptr = (unsigned char *) inputToken.value;
  code = gssint_g_verify_token_header(gss_mech_krb5, //always use krb5
                                      &(ap_rep.length),
                                      &ptr,
                                      KG_TOK_CTX_AP_REP,
                                      inputToken.length, 1);

  if (code) {
    onError("Failed to verify ap_rep input token header");
    return;
  }

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

  code = decode_krb5_ap_rep(&ap_rep, &reply);
  if (code) {
    onError("Cannot decode ap_rep");
    return;
  }

  SCOPE_EXIT {
    krb5_free_ap_rep(ctx_->get(), reply);
  };

  krb5_data scratch;
  scratch.length = reply->enc_part.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_REP_ENCPART,
                        0,
                        &reply->enc_part,
                        &scratch);
  if (code) {
    onError("Cannot decrypt ap_rep");
    return;
  }

  code = decode_krb5_ap_rep_enc_part(&scratch, &enc);
  if (code) {
    onError("Cannot decode ap_rep's encrypted part");
    return;
  }

  SCOPE_EXIT {
    krb5_free_ap_rep_enc_part(ctx_->get(), enc);
  };

  // If subkey is present in ap_rep, it is used for encrypt/decrypt
  // application messages.
  if (enc->subkey) {
    krb5_copy_keyblock(ctx_->get(), enc->subkey, &subkey_);
    krb5_free_keyblock(ctx_->get(), sessionKey_);
    sessionKey_ = nullptr;
  }
}