Esempio n. 1
0
/*
  Validate an incoming authenticator against the credentials for the remote machine.

  The credentials are (re)read and from the schannel database, and
  written back after the caclulations are performed.

  The creds_out parameter (if not NULL) returns the credentials, if
  the caller needs some of that information.

*/
NTSTATUS schannel_creds_server_step_check_ldb(struct ldb_context *ldb,
					      TALLOC_CTX *mem_ctx,
					      const char *computer_name,
					      bool schannel_required_for_call,
					      bool schannel_in_use,
					      struct netr_Authenticator *received_authenticator,
					      struct netr_Authenticator *return_authenticator,
					      struct netlogon_creds_CredentialState **creds_out)
{
	struct netlogon_creds_CredentialState *creds;
	NTSTATUS nt_status;
	int ret;

	ret = ldb_transaction_start(ldb);
	if (ret != 0) {
		return NT_STATUS_INTERNAL_DB_CORRUPTION;
	}

	/* Because this is a shared structure (even across
	 * disconnects) we must update the database every time we
	 * update the structure */

	nt_status = schannel_fetch_session_key_ldb(ldb, ldb, computer_name,
						   &creds);

	/* If we are flaged that schannel is required for a call, and
	 * it is not in use, then make this an error */

	/* It would be good to make this mandetory once schannel is
	 * negoiated, bu this is not what windows does */
	if (schannel_required_for_call && !schannel_in_use) {
		DEBUG(0,("schannel_creds_server_step_check: client %s not using schannel for netlogon, despite negotiating it\n",
			creds->computer_name ));
		ldb_transaction_cancel(ldb);
		return NT_STATUS_ACCESS_DENIED;
	}

	if (NT_STATUS_IS_OK(nt_status)) {
		nt_status = netlogon_creds_server_step_check(creds,
							     received_authenticator,
							     return_authenticator);
	}

	if (NT_STATUS_IS_OK(nt_status)) {
		nt_status = schannel_store_session_key_ldb(ldb, mem_ctx, creds);
	}

	if (NT_STATUS_IS_OK(nt_status)) {
		ldb_transaction_commit(ldb);
		if (creds_out) {
			*creds_out = creds;
			talloc_steal(mem_ctx, creds);
		}
	} else {
		ldb_transaction_cancel(ldb);
	}
	return nt_status;
}
Esempio n. 2
0
NTSTATUS schannel_check_creds_state(TALLOC_CTX *mem_ctx,
				    struct loadparm_context *lp_ctx,
				    const char *computer_name,
				    struct netr_Authenticator *received_authenticator,
				    struct netr_Authenticator *return_authenticator,
				    struct netlogon_creds_CredentialState **creds_out)
{
	TALLOC_CTX *tmpctx;
	struct tdb_wrap *tdb_sc;
	struct netlogon_creds_CredentialState *creds;
	NTSTATUS status;
	int ret;

	tmpctx = talloc_named(mem_ctx, 0, "schannel_check_creds_state");
	if (!tmpctx) {
		return NT_STATUS_NO_MEMORY;
	}

	tdb_sc = open_schannel_session_store(tmpctx, lp_ctx);
	if (!tdb_sc) {
		status = NT_STATUS_ACCESS_DENIED;
		goto done;
	}

	ret = tdb_transaction_start(tdb_sc->tdb);
	if (ret != 0) {
		status = NT_STATUS_INTERNAL_DB_CORRUPTION;
		goto done;
	}

	/* Because this is a shared structure (even across
	 * disconnects) we must update the database every time we
	 * update the structure */

	status = schannel_fetch_session_key_tdb(tdb_sc, tmpctx, 
						computer_name, &creds);
	if (!NT_STATUS_IS_OK(status)) {
		tdb_transaction_cancel(tdb_sc->tdb);
		goto done;
	}

	status = netlogon_creds_server_step_check(creds,
						  received_authenticator,
						  return_authenticator);
	if (!NT_STATUS_IS_OK(status)) {
		tdb_transaction_cancel(tdb_sc->tdb);
		goto done;
	}

	status = schannel_store_session_key_tdb(tdb_sc, tmpctx, creds);
	if (!NT_STATUS_IS_OK(status)) {
		tdb_transaction_cancel(tdb_sc->tdb);
		goto done;
	}

	tdb_transaction_commit(tdb_sc->tdb);

	if (creds_out) {
		*creds_out = talloc_steal(mem_ctx, creds);
		if (!*creds_out) {
			status = NT_STATUS_NO_MEMORY;
			goto done;
		}
	}

	status = NT_STATUS_OK;

done:
	talloc_free(tmpctx);
	return status;
}