NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli,
				   TALLOC_CTX *mem_ctx,
				   uint32 logon_parameters,
				   const char *domain,
				   const char *username,
				   const char *password,
				   const char *workstation,
				   uint16_t validation_level,
				   int logon_type)
{
	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
	NTSTATUS status;
	struct netr_Authenticator clnt_creds;
	struct netr_Authenticator ret_creds;
	union netr_LogonLevel *logon;
	union netr_Validation validation;
	uint8_t authoritative;
	fstring clnt_name_slash;
	struct dcerpc_binding_handle *b = cli->binding_handle;

	ZERO_STRUCT(ret_creds);

	logon = talloc_zero(mem_ctx, union netr_LogonLevel);
	if (!logon) {
		return NT_STATUS_NO_MEMORY;
	}

	if (workstation) {
		fstr_sprintf( clnt_name_slash, "\\\\%s", workstation );
	} else {
		fstr_sprintf( clnt_name_slash, "\\\\%s", lp_netbios_name() );
	}

	/* Initialise input parameters */

	netlogon_creds_client_authenticator(cli->dc, &clnt_creds);

	switch (logon_type) {
	case NetlogonInteractiveInformation: {

		struct netr_PasswordInfo *password_info;

		struct samr_Password lmpassword;
		struct samr_Password ntpassword;

		password_info = talloc_zero(mem_ctx, struct netr_PasswordInfo);
		if (!password_info) {
			return NT_STATUS_NO_MEMORY;
		}

		nt_lm_owf_gen(password, ntpassword.hash, lmpassword.hash);

		if (cli->dc->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
			netlogon_creds_aes_encrypt(cli->dc, lmpassword.hash, 16);
			netlogon_creds_aes_encrypt(cli->dc, ntpassword.hash, 16);
		} else if (cli->dc->negotiate_flags & NETLOGON_NEG_ARCFOUR) {
			netlogon_creds_arcfour_crypt(cli->dc, lmpassword.hash, 16);
			netlogon_creds_arcfour_crypt(cli->dc, ntpassword.hash, 16);
		} else {
			netlogon_creds_des_encrypt(cli->dc, &lmpassword);
			netlogon_creds_des_encrypt(cli->dc, &ntpassword);
		}

		password_info->identity_info.domain_name.string		= domain;
		password_info->identity_info.parameter_control		= logon_parameters;
		password_info->identity_info.logon_id_low		= 0xdead;
		password_info->identity_info.logon_id_high		= 0xbeef;
		password_info->identity_info.account_name.string	= username;
		password_info->identity_info.workstation.string		= clnt_name_slash;

		password_info->lmpassword = lmpassword;
		password_info->ntpassword = ntpassword;

		logon->password = password_info;

		break;
	}
	case NetlogonNetworkInformation: {
		struct netr_NetworkInfo *network_info;
		uint8 chal[8];
		unsigned char local_lm_response[24];
		unsigned char local_nt_response[24];
		struct netr_ChallengeResponse lm;
		struct netr_ChallengeResponse nt;

		ZERO_STRUCT(lm);
		ZERO_STRUCT(nt);

		network_info = talloc_zero(mem_ctx, struct netr_NetworkInfo);
		if (!network_info) {
			return NT_STATUS_NO_MEMORY;
		}

		generate_random_buffer(chal, 8);

		SMBencrypt(password, chal, local_lm_response);
		SMBNTencrypt(password, chal, local_nt_response);

		lm.length = 24;
		lm.data = local_lm_response;

		nt.length = 24;
		nt.data = local_nt_response;

		network_info->identity_info.domain_name.string		= domain;
		network_info->identity_info.parameter_control		= logon_parameters;
		network_info->identity_info.logon_id_low		= 0xdead;
		network_info->identity_info.logon_id_high		= 0xbeef;
		network_info->identity_info.account_name.string		= username;
		network_info->identity_info.workstation.string		= clnt_name_slash;

		memcpy(network_info->challenge, chal, 8);
		network_info->nt = nt;
		network_info->lm = lm;

		logon->network = network_info;

		break;
	}
	default:
		DEBUG(0, ("switch value %d not supported\n",
			logon_type));
		return NT_STATUS_INVALID_INFO_CLASS;
	}

	status = dcerpc_netr_LogonSamLogon(b, mem_ctx,
					   cli->srv_name_slash,
					   lp_netbios_name(),
					   &clnt_creds,
					   &ret_creds,
					   logon_type,
					   logon,
					   validation_level,
					   &validation,
					   &authoritative,
					   &result);
	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	/* Always check returned credentials */
	if (!netlogon_creds_client_check(cli->dc, &ret_creds.cred)) {
		DEBUG(0,("rpccli_netlogon_sam_logon: credentials chain check failed\n"));
		return NT_STATUS_ACCESS_DENIED;
	}

	return result;
}
NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli,
					   TALLOC_CTX *mem_ctx,
					   uint32 logon_parameters,
					   const char *server,
					   const char *username,
					   const char *domain,
					   const char *workstation,
					   const uint8 chal[8],
					   uint16_t validation_level,
					   DATA_BLOB lm_response,
					   DATA_BLOB nt_response,
					   struct netr_SamInfo3 **info3)
{
	NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
	NTSTATUS status;
	const char *workstation_name_slash;
	const char *server_name_slash;
	struct netr_Authenticator clnt_creds;
	struct netr_Authenticator ret_creds;
	union netr_LogonLevel *logon = NULL;
	struct netr_NetworkInfo *network_info;
	uint8_t authoritative;
	union netr_Validation validation;
	struct netr_ChallengeResponse lm;
	struct netr_ChallengeResponse nt;
	struct dcerpc_binding_handle *b = cli->binding_handle;

	*info3 = NULL;

	ZERO_STRUCT(ret_creds);

	ZERO_STRUCT(lm);
	ZERO_STRUCT(nt);

	logon = talloc_zero(mem_ctx, union netr_LogonLevel);
	if (!logon) {
		return NT_STATUS_NO_MEMORY;
	}

	network_info = talloc_zero(mem_ctx, struct netr_NetworkInfo);
	if (!network_info) {
		return NT_STATUS_NO_MEMORY;
	}

	netlogon_creds_client_authenticator(cli->dc, &clnt_creds);

	if (server[0] != '\\' && server[1] != '\\') {
		server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server);
	} else {
		server_name_slash = server;
	}

	if (workstation[0] != '\\' && workstation[1] != '\\') {
		workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation);
	} else {
		workstation_name_slash = workstation;
	}

	if (!workstation_name_slash || !server_name_slash) {
		DEBUG(0, ("talloc_asprintf failed!\n"));
		return NT_STATUS_NO_MEMORY;
	}

	/* Initialise input parameters */

	lm.data = lm_response.data;
	lm.length = lm_response.length;
	nt.data = nt_response.data;
	nt.length = nt_response.length;

	network_info->identity_info.domain_name.string		= domain;
	network_info->identity_info.parameter_control		= logon_parameters;
	network_info->identity_info.logon_id_low		= 0xdead;
	network_info->identity_info.logon_id_high		= 0xbeef;
	network_info->identity_info.account_name.string		= username;
	network_info->identity_info.workstation.string		= workstation_name_slash;

	memcpy(network_info->challenge, chal, 8);
	network_info->nt = nt;
	network_info->lm = lm;

	logon->network = network_info;

	/* Marshall data and send request */

	status = dcerpc_netr_LogonSamLogon(b, mem_ctx,
					   server_name_slash,
					   lp_netbios_name(),
					   &clnt_creds,
					   &ret_creds,
					   NetlogonNetworkInformation,
					   logon,
					   validation_level,
					   &validation,
					   &authoritative,
					   &result);
	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	/* Always check returned credentials. */
	if (!netlogon_creds_client_check(cli->dc, &ret_creds.cred)) {
		DEBUG(0,("rpccli_netlogon_sam_network_logon: credentials chain check failed\n"));
		return NT_STATUS_ACCESS_DENIED;
	}

	if (!NT_STATUS_IS_OK(result)) {
		return result;
	}

	netlogon_creds_decrypt_samlogon_validation(cli->dc, validation_level,
						   &validation);

	result = map_validation_to_info3(mem_ctx, validation_level, &validation, info3);
	if (!NT_STATUS_IS_OK(result)) {
		return result;
	}

	return result;
}
Esempio n. 3
0
static bool test_PACVerify(struct torture_context *tctx,
                           struct dcerpc_pipe *p,
                           struct cli_credentials *credentials)
{
    NTSTATUS status;

    struct netr_LogonSamLogon r;

    union netr_LogonLevel logon;
    union netr_Validation validation;
    uint8_t authoritative;
    struct netr_Authenticator return_authenticator;

    struct netr_GenericInfo generic;
    struct netr_Authenticator auth, auth2;


    struct netlogon_creds_CredentialState *creds;
    struct gensec_security *gensec_client_context;
    struct gensec_security *gensec_server_context;

    DATA_BLOB client_to_server, server_to_client, pac_wrapped, payload;
    struct PAC_Validate pac_wrapped_struct;

    enum ndr_err_code ndr_err;

    struct auth_session_info *session_info;

    char *tmp_dir;

    TALLOC_CTX *tmp_ctx = talloc_new(tctx);

    torture_assert(tctx, tmp_ctx != NULL, "talloc_new() failed");

    if (!test_SetupCredentials2(p, tctx, NETLOGON_NEG_AUTH2_ADS_FLAGS,
                                credentials, SEC_CHAN_BDC,
                                &creds)) {
        return false;
    }

    status = torture_temp_dir(tctx, "PACVerify", &tmp_dir);
    torture_assert_ntstatus_ok(tctx, status, "torture_temp_dir failed");

    status = gensec_client_start(tctx, &gensec_client_context, tctx->ev,
                                 lp_gensec_settings(tctx, tctx->lp_ctx));
    torture_assert_ntstatus_ok(tctx, status, "gensec_client_start (client) failed");

    status = gensec_set_target_hostname(gensec_client_context, TEST_MACHINE_NAME);

    status = gensec_set_credentials(gensec_client_context, cmdline_credentials);
    torture_assert_ntstatus_ok(tctx, status, "gensec_set_credentials (client) failed");

    status = gensec_start_mech_by_sasl_name(gensec_client_context, "GSSAPI");
    torture_assert_ntstatus_ok(tctx, status, "gensec_start_mech_by_sasl_name (client) failed");

    status = gensec_server_start(tctx, tctx->ev,
                                 lp_gensec_settings(tctx, tctx->lp_ctx),
                                 NULL, &gensec_server_context);
    torture_assert_ntstatus_ok(tctx, status, "gensec_server_start (server) failed");

    status = gensec_set_credentials(gensec_server_context, credentials);
    torture_assert_ntstatus_ok(tctx, status, "gensec_set_credentials (server) failed");

    status = gensec_start_mech_by_sasl_name(gensec_server_context, "GSSAPI");
    torture_assert_ntstatus_ok(tctx, status, "gensec_start_mech_by_sasl_name (server) failed");

    server_to_client = data_blob(NULL, 0);

    do {
        /* Do a client-server update dance */
        status = gensec_update(gensec_client_context, tmp_ctx, server_to_client, &client_to_server);
        if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
            ;
            torture_assert_ntstatus_ok(tctx, status, "gensec_update (client) failed");
        }

        status = gensec_update(gensec_server_context, tmp_ctx, client_to_server, &server_to_client);
        if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
            ;
            torture_assert_ntstatus_ok(tctx, status, "gensec_update (server) failed");
        }

        if (NT_STATUS_IS_OK(status)) {
            break;
        }
    } while (1);

    /* Extract the PAC using Samba's code */

    status = gensec_session_info(gensec_server_context, &session_info);
    torture_assert_ntstatus_ok(tctx, status, "gensec_session_info failed");

    pac_wrapped_struct.ChecksumLength = session_info->server_info->pac_srv_sig.signature.length;
    pac_wrapped_struct.SignatureType = session_info->server_info->pac_kdc_sig.type;
    pac_wrapped_struct.SignatureLength = session_info->server_info->pac_kdc_sig.signature.length;
    pac_wrapped_struct.ChecksumAndSignature = payload
            = data_blob_talloc(tmp_ctx, NULL,
                               pac_wrapped_struct.ChecksumLength
                               + pac_wrapped_struct.SignatureLength);
    memcpy(&payload.data[0],
           session_info->server_info->pac_srv_sig.signature.data,
           pac_wrapped_struct.ChecksumLength);
    memcpy(&payload.data[pac_wrapped_struct.ChecksumLength],
           session_info->server_info->pac_kdc_sig.signature.data,
           pac_wrapped_struct.SignatureLength);

    ndr_err = ndr_push_struct_blob(&pac_wrapped, tmp_ctx, lp_iconv_convenience(tctx->lp_ctx), &pac_wrapped_struct,
                                   (ndr_push_flags_fn_t)ndr_push_PAC_Validate);
    torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), "ndr_push_struct_blob of PACValidate structure failed");

    torture_assert(tctx, (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR), "not willing to even try a PACValidate without RC4 encryption");
    netlogon_creds_arcfour_crypt(creds, pac_wrapped.data, pac_wrapped.length);

    generic.length = pac_wrapped.length;
    generic.data = pac_wrapped.data;

    /* Validate it over the netlogon pipe */

    generic.identity_info.parameter_control = 0;
    generic.identity_info.logon_id_high = 0;
    generic.identity_info.logon_id_low = 0;
    generic.identity_info.domain_name.string = session_info->server_info->domain_name;
    generic.identity_info.account_name.string = session_info->server_info->account_name;
    generic.identity_info.workstation.string = TEST_MACHINE_NAME;

    generic.package_name.string = "Kerberos";

    logon.generic = &generic;

    ZERO_STRUCT(auth2);
    netlogon_creds_client_authenticator(creds, &auth);
    r.in.credential = &auth;
    r.in.return_authenticator = &auth2;
    r.in.logon = &logon;
    r.in.logon_level = NetlogonGenericInformation;
    r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
    r.in.computer_name = cli_credentials_get_workstation(credentials);
    r.in.validation_level = NetlogonValidationGenericInfo2;
    r.out.validation = &validation;
    r.out.authoritative = &authoritative;
    r.out.return_authenticator = &return_authenticator;

    status = dcerpc_netr_LogonSamLogon(p, tctx, &r);

    torture_assert_ntstatus_ok(tctx, status, "LogonSamLogon failed");

    /* This will break the signature nicely (even in the crypto wrapping), check we get a logon failure */
    generic.data[generic.length-1]++;

    logon.generic = &generic;

    ZERO_STRUCT(auth2);
    netlogon_creds_client_authenticator(creds, &auth);
    r.in.credential = &auth;
    r.in.return_authenticator = &auth2;
    r.in.logon_level = NetlogonGenericInformation;
    r.in.logon = &logon;
    r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
    r.in.computer_name = cli_credentials_get_workstation(credentials);
    r.in.validation_level = NetlogonValidationGenericInfo2;

    status = dcerpc_netr_LogonSamLogon(p, tctx, &r);

    torture_assert_ntstatus_equal(tctx, status, NT_STATUS_LOGON_FAILURE, "LogonSamLogon failed");

    torture_assert(tctx, netlogon_creds_client_check(creds, &r.out.return_authenticator->cred),
                   "Credential chaining failed");

    /* This will break the parsing nicely (even in the crypto wrapping), check we get INVALID_PARAMETER */
    generic.length--;

    logon.generic = &generic;

    ZERO_STRUCT(auth2);
    netlogon_creds_client_authenticator(creds, &auth);
    r.in.credential = &auth;
    r.in.return_authenticator = &auth2;
    r.in.logon_level = NetlogonGenericInformation;
    r.in.logon = &logon;
    r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
    r.in.computer_name = cli_credentials_get_workstation(credentials);
    r.in.validation_level = NetlogonValidationGenericInfo2;

    status = dcerpc_netr_LogonSamLogon(p, tctx, &r);

    torture_assert_ntstatus_equal(tctx, status, NT_STATUS_INVALID_PARAMETER, "LogonSamLogon failed");

    torture_assert(tctx, netlogon_creds_client_check(creds,
                   &r.out.return_authenticator->cred),
                   "Credential chaining failed");

    pac_wrapped_struct.ChecksumLength = session_info->server_info->pac_srv_sig.signature.length;
    pac_wrapped_struct.SignatureType = session_info->server_info->pac_kdc_sig.type;

    /* Break the SignatureType */
    pac_wrapped_struct.SignatureType++;

    pac_wrapped_struct.SignatureLength = session_info->server_info->pac_kdc_sig.signature.length;
    pac_wrapped_struct.ChecksumAndSignature = payload
            = data_blob_talloc(tmp_ctx, NULL,
                               pac_wrapped_struct.ChecksumLength
                               + pac_wrapped_struct.SignatureLength);
    memcpy(&payload.data[0],
           session_info->server_info->pac_srv_sig.signature.data,
           pac_wrapped_struct.ChecksumLength);
    memcpy(&payload.data[pac_wrapped_struct.ChecksumLength],
           session_info->server_info->pac_kdc_sig.signature.data,
           pac_wrapped_struct.SignatureLength);

    ndr_err = ndr_push_struct_blob(&pac_wrapped, tmp_ctx, lp_iconv_convenience(tctx->lp_ctx), &pac_wrapped_struct,
                                   (ndr_push_flags_fn_t)ndr_push_PAC_Validate);
    torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), "ndr_push_struct_blob of PACValidate structure failed");

    torture_assert(tctx, (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR), "not willing to even try a PACValidate without RC4 encryption");
    netlogon_creds_arcfour_crypt(creds, pac_wrapped.data, pac_wrapped.length);

    generic.length = pac_wrapped.length;
    generic.data = pac_wrapped.data;

    logon.generic = &generic;

    ZERO_STRUCT(auth2);
    netlogon_creds_client_authenticator(creds, &auth);
    r.in.credential = &auth;
    r.in.return_authenticator = &auth2;
    r.in.logon_level = NetlogonGenericInformation;
    r.in.logon = &logon;
    r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
    r.in.computer_name = cli_credentials_get_workstation(credentials);
    r.in.validation_level = NetlogonValidationGenericInfo2;

    status = dcerpc_netr_LogonSamLogon(p, tctx, &r);

    torture_assert_ntstatus_equal(tctx, status, NT_STATUS_LOGON_FAILURE, "LogonSamLogon failed");

    torture_assert(tctx, netlogon_creds_client_check(creds, &r.out.return_authenticator->cred),
                   "Credential chaining failed");

    pac_wrapped_struct.ChecksumLength = session_info->server_info->pac_srv_sig.signature.length;
    pac_wrapped_struct.SignatureType = session_info->server_info->pac_kdc_sig.type;
    pac_wrapped_struct.SignatureLength = session_info->server_info->pac_kdc_sig.signature.length;

    pac_wrapped_struct.ChecksumAndSignature = payload
            = data_blob_talloc(tmp_ctx, NULL,
                               pac_wrapped_struct.ChecksumLength
                               + pac_wrapped_struct.SignatureLength);
    memcpy(&payload.data[0],
           session_info->server_info->pac_srv_sig.signature.data,
           pac_wrapped_struct.ChecksumLength);
    memcpy(&payload.data[pac_wrapped_struct.ChecksumLength],
           session_info->server_info->pac_kdc_sig.signature.data,
           pac_wrapped_struct.SignatureLength);

    /* Break the signature length */
    pac_wrapped_struct.SignatureLength++;

    ndr_err = ndr_push_struct_blob(&pac_wrapped, tmp_ctx, lp_iconv_convenience(tctx->lp_ctx), &pac_wrapped_struct,
                                   (ndr_push_flags_fn_t)ndr_push_PAC_Validate);
    torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), "ndr_push_struct_blob of PACValidate structure failed");

    torture_assert(tctx, (creds->negotiate_flags & NETLOGON_NEG_ARCFOUR), "not willing to even try a PACValidate without RC4 encryption");
    netlogon_creds_arcfour_crypt(creds, pac_wrapped.data, pac_wrapped.length);

    generic.length = pac_wrapped.length;
    generic.data = pac_wrapped.data;

    logon.generic = &generic;

    ZERO_STRUCT(auth2);
    netlogon_creds_client_authenticator(creds, &auth);
    r.in.credential = &auth;
    r.in.return_authenticator = &auth2;
    r.in.logon_level = NetlogonGenericInformation;
    r.in.logon = &logon;
    r.in.server_name = talloc_asprintf(tctx, "\\\\%s", dcerpc_server_name(p));
    r.in.computer_name = cli_credentials_get_workstation(credentials);
    r.in.validation_level = NetlogonValidationGenericInfo2;

    status = dcerpc_netr_LogonSamLogon(p, tctx, &r);

    torture_assert_ntstatus_equal(tctx, status, NT_STATUS_INVALID_PARAMETER, "LogonSamLogon failed");

    torture_assert(tctx, netlogon_creds_client_check(creds, &r.out.return_authenticator->cred),
                   "Credential chaining failed");
    return true;
}