Exemple #1
0
NTSTATUS ntlmssp_seal_packet(NTLMSSP_STATE *ntlmssp_state,
			     uchar *data, size_t length,
			     uchar *whole_pdu, size_t pdu_length,
			     DATA_BLOB *sig)
{	
	if (!(ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL)) {
		DEBUG(3, ("NTLMSSP Sealing not negotiated - cannot seal packet!\n"));
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (!ntlmssp_state->session_key.length) {
		DEBUG(3, ("NO session key, cannot seal packet\n"));
		return NT_STATUS_NO_USER_SESSION_KEY;
	}

	DEBUG(10,("ntlmssp_seal_data: seal\n"));
	dump_data_pw("ntlmssp clear data\n", data, length);
	if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
		/* The order of these two operations matters - we must first seal the packet,
		   then seal the sequence number - this is becouse the send_seal_hash is not
		   constant, but is is rather updated with each iteration */
		NTSTATUS nt_status = ntlmssp_make_packet_signature(ntlmssp_state,
							data, length,
							whole_pdu, pdu_length,
							NTLMSSP_SEND, sig, False);
		if (!NT_STATUS_IS_OK(nt_status)) {
			return nt_status;
		}

		arcfour_crypt_sbox(&ntlmssp_state->send_seal_arc4_state, data, length);
		if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
			arcfour_crypt_sbox(&ntlmssp_state->send_seal_arc4_state, sig->data+4, 8);
		}
	} else {
		uint32 crc;
		crc = crc32_calc_buffer(data, length);
		if (!msrpc_gen(sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, ntlmssp_state->ntlmv1_seq_num)) {
			return NT_STATUS_NO_MEMORY;
		}

		/* The order of these two operations matters - we must first seal the packet,
		   then seal the sequence number - this is becouse the ntlmv1_arc4_state is not
		   constant, but is is rather updated with each iteration */
		
		dump_arc4_state("ntlmv1 arc4 state:\n", 
						&ntlmssp_state->ntlmv1_arc4_state);
		arcfour_crypt_sbox(&ntlmssp_state->ntlmv1_arc4_state, data, length);

		dump_arc4_state("ntlmv1 arc4 state:\n", 
						&ntlmssp_state->ntlmv1_arc4_state);

		arcfour_crypt_sbox(&ntlmssp_state->ntlmv1_arc4_state, sig->data+4, sig->length-4);

		ntlmssp_state->ntlmv1_seq_num++;
	}
	dump_data_pw("ntlmssp signature\n", sig->data, sig->length);
	dump_data_pw("ntlmssp sealed data\n", data, length);

	return NT_STATUS_OK;
}
Exemple #2
0
// START FUNC DECL
void
crc32_I8( 
		    unsigned long long *in, 
		    long long nR, 
		    uint32_t *out
		    )
// STOP FUNC DECL
{
  int sz = sizeof(long long);
  for ( long long i = 0; i < nR; i++ ) { 
    long long inval = in[i];
    const uint8_t *data_ptr = (const uint8_t *)(&inval);
    uint32_t outval = crc32_calc_buffer(data_ptr, sz);
    out[i] = outval;
  }
}
Exemple #3
0
static NTSTATUS ntlmssp_make_packet_signature(NTLMSSP_STATE *ntlmssp_state,
        const uchar *data, size_t length,
        enum ntlmssp_direction direction,
        DATA_BLOB *sig)
{
    if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
        HMACMD5Context ctx;
        uchar seq_num[4];
        uchar digest[16];
        SIVAL(seq_num, 0, ntlmssp_state->ntlmssp_seq_num);

        hmac_md5_init_limK_to_64((const unsigned char *)(ntlmssp_state->send_sign_const), 16, &ctx);
        hmac_md5_update(seq_num, 4, &ctx);
        hmac_md5_update(data, length, &ctx);
        hmac_md5_final(digest, &ctx);

        if (!msrpc_gen(sig, "dBd", NTLMSSP_SIGN_VERSION, digest, 8 /* only copy first 8 bytes */
                       , ntlmssp_state->ntlmssp_seq_num)) {
            return NT_STATUS_NO_MEMORY;
        }

        if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
            switch (direction) {
            case NTLMSSP_SEND:
                NTLMSSPcalc_ap(ntlmssp_state->send_sign_hash,  sig->data+4, sig->length-4);
                break;
            case NTLMSSP_RECEIVE:
                NTLMSSPcalc_ap(ntlmssp_state->recv_sign_hash,  sig->data+4, sig->length-4);
                break;
            }
        }
    } else {
        uint32 crc;
        crc = crc32_calc_buffer((const char *)data, length);
        if (!msrpc_gen(sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, ntlmssp_state->ntlmssp_seq_num)) {
            return NT_STATUS_NO_MEMORY;
        }

        dump_data_pw("ntlmssp hash:\n", ntlmssp_state->ntlmssp_hash,
                     sizeof(ntlmssp_state->ntlmssp_hash));
        NTLMSSPcalc_ap(ntlmssp_state->ntlmssp_hash, sig->data+4, sig->length-4);
    }
    return NT_STATUS_OK;
}
Exemple #4
0
int plf_write_payload(int fileIdx, int sectIndx, const void* buffer, u32 len, u8 compress)
{
    u32 bytes_written;
    s_plf_file_entry* fileEntry;
    s_plf_section_entry* sectEntry;

    PLF_VERIFY_IDX(fileIdx);

    fileEntry = &plf_files[fileIdx];

    if (sectIndx > fileEntry->num_entries || buffer == 0)
        return PLF_E_PARAM;

    /* Check if this filentry is writable */
    if ( (fileEntry->flags & PLF_FILE_FLAG_WRITE) == 0)
        return PLF_E_WRITE;

    /* Check if section previous section is opened */
    if ( (fileEntry->flags & PLF_FILE_FLAG_SECTOPEN) == 0)
        return PLF_E_NOT_OPENED;

    if (compress != 0)
        return PLF_E_NOT_IMPLEMENTED;

    sectEntry = plf_int_get_section(fileIdx, sectIndx);

    bytes_written =  plf_int_write(fileIdx, buffer, fileEntry->current_size, len);

    if (bytes_written > 0)
    {
        u32 num_crc=0;
        fileEntry->current_size += bytes_written;
        sectEntry->hdr.dwSectionSize += bytes_written;

        crc32_calc_buffer(&sectEntry->hdr.dwCRC32, &num_crc, buffer, bytes_written);
    }

    return bytes_written;
}
Exemple #5
0
NTSTATUS ntlmssp_seal_packet(NTLMSSP_STATE *ntlmssp_state,
                             uchar *data, size_t length,
                             DATA_BLOB *sig)
{
    if (!ntlmssp_state->session_key.length) {
        DEBUG(3, ("NO session key, cannot seal packet\n"));
        return NT_STATUS_NO_USER_SESSION_KEY;
    }

    DEBUG(10,("ntlmssp_seal_data: seal\n"));
    dump_data_pw("ntlmssp clear data\n", data, length);
    if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
        HMACMD5Context ctx;
        char seq_num[4];
        uchar digest[16];
        SIVAL(seq_num, 0, ntlmssp_state->ntlmssp_seq_num);

        hmac_md5_init_limK_to_64((const unsigned char *)(ntlmssp_state->send_sign_const), 16, &ctx);
        hmac_md5_update((const unsigned char *)seq_num, 4, &ctx);
        hmac_md5_update(data, length, &ctx);
        hmac_md5_final(digest, &ctx);

        if (!msrpc_gen(sig, "dBd", NTLMSSP_SIGN_VERSION, digest, 8 /* only copy first 8 bytes */
                       , ntlmssp_state->ntlmssp_seq_num)) {
            return NT_STATUS_NO_MEMORY;
        }

        dump_data_pw("ntlmssp client sealing hash:\n",
                     ntlmssp_state->send_seal_hash,
                     sizeof(ntlmssp_state->send_seal_hash));
        NTLMSSPcalc_ap(ntlmssp_state->send_seal_hash, data, length);
        dump_data_pw("ntlmssp client signing hash:\n",
                     ntlmssp_state->send_sign_hash,
                     sizeof(ntlmssp_state->send_sign_hash));
        NTLMSSPcalc_ap(ntlmssp_state->send_sign_hash,  sig->data+4, sig->length-4);
    } else {
        uint32 crc;
        crc = crc32_calc_buffer((const char *)data, length);
        if (!msrpc_gen(sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, ntlmssp_state->ntlmssp_seq_num)) {
            return NT_STATUS_NO_MEMORY;
        }

        /* The order of these two operations matters - we must first seal the packet,
           then seal the sequence number - this is becouse the ntlmssp_hash is not
           constant, but is is rather updated with each iteration */

        dump_data_pw("ntlmssp hash:\n", ntlmssp_state->ntlmssp_hash,
                     sizeof(ntlmssp_state->ntlmssp_hash));
        NTLMSSPcalc_ap(ntlmssp_state->ntlmssp_hash, data, length);

        dump_data_pw("ntlmssp hash:\n", ntlmssp_state->ntlmssp_hash,
                     sizeof(ntlmssp_state->ntlmssp_hash));
        NTLMSSPcalc_ap(ntlmssp_state->ntlmssp_hash, sig->data+4, sig->length-4);
    }
    dump_data_pw("ntlmssp sealed data\n", data, length);

    /* increment counter on send */
    ntlmssp_state->ntlmssp_seq_num++;

    return NT_STATUS_OK;
}
WERROR drsuapi_decrypt_attribute_value(TALLOC_CTX *mem_ctx,
				       const DATA_BLOB *gensec_skey,
				       bool rid_crypt,
				       uint32_t rid,
				       DATA_BLOB *in,
				       DATA_BLOB *out)
{
	DATA_BLOB confounder;
	DATA_BLOB enc_buffer;

	MD5_CTX md5;
	uint8_t _enc_key[16];
	DATA_BLOB enc_key;

	DATA_BLOB dec_buffer;

	uint32_t crc32_given;
	uint32_t crc32_calc;
	DATA_BLOB checked_buffer;

	DATA_BLOB plain_buffer;

	/*
	 * users with rid == 0 should not exist
	 */
	if (rid_crypt && rid == 0) {
		return WERR_DS_DRA_INVALID_PARAMETER;
	}

	/* 
	 * the first 16 bytes at the beginning are the confounder
	 * followed by the 4 byte crc32 checksum
	 */
	if (in->length < 20) {
		return WERR_DS_DRA_INVALID_PARAMETER;
	}
	confounder = data_blob_const(in->data, 16);
	enc_buffer = data_blob_const(in->data + 16, in->length - 16);

	/* 
	 * build the encryption key md5 over the session key followed
	 * by the confounder
	 * 
	 * here the gensec session key is used and
	 * not the dcerpc ncacn_ip_tcp "SystemLibraryDTC" key!
	 */
	enc_key = data_blob_const(_enc_key, sizeof(_enc_key));
	MD5Init(&md5);
	MD5Update(&md5, gensec_skey->data, gensec_skey->length);
	MD5Update(&md5, confounder.data, confounder.length);
	MD5Final(enc_key.data, &md5);

	/*
	 * copy the encrypted buffer part and 
	 * decrypt it using the created encryption key using arcfour
	 */
	dec_buffer = data_blob_const(enc_buffer.data, enc_buffer.length);
	arcfour_crypt_blob(dec_buffer.data, dec_buffer.length, &enc_key);

	/* 
	 * the first 4 byte are the crc32 checksum
	 * of the remaining bytes
	 */
	crc32_given = IVAL(dec_buffer.data, 0);
	crc32_calc = crc32_calc_buffer(dec_buffer.data + 4 , dec_buffer.length - 4);
	checked_buffer = data_blob_const(dec_buffer.data + 4, dec_buffer.length - 4);

	plain_buffer = data_blob_talloc(mem_ctx, checked_buffer.data, checked_buffer.length);
	W_ERROR_HAVE_NO_MEMORY(plain_buffer.data);

	if (crc32_given != crc32_calc) {
		return WERR_SEC_E_DECRYPT_FAILURE;
	}
	/*
	 * The following rid_crypt obfuscation isn't session specific
	 * and not really needed here, because we allways know the rid of the
	 * user account.
	 *
	 * some attributes with this 'additional encryption' include
	 * dBCSPwd, unicodePwd, ntPwdHistory, lmPwdHistory
	 *
	 * But for the rest of samba it's easier when we remove this static
	 * obfuscation here
	 */
	if (rid_crypt) {
		uint32_t i, num_hashes;

		if ((checked_buffer.length % 16) != 0) {
			return WERR_DS_DRA_INVALID_PARAMETER;
		}

		num_hashes = plain_buffer.length / 16;
		for (i = 0; i < num_hashes; i++) {
			uint32_t offset = i * 16;
			sam_rid_crypt(rid, checked_buffer.data + offset, plain_buffer.data + offset, 0);
		}
	}

	*out = plain_buffer;
	return WERR_OK;
}
static WERROR drsuapi_encrypt_attribute_value(TALLOC_CTX *mem_ctx,
					      const DATA_BLOB *gensec_skey,
					      bool rid_crypt,
					      uint32_t rid,
					      DATA_BLOB *in,
					      DATA_BLOB *out)
{
	DATA_BLOB rid_crypt_out = data_blob(NULL, 0);
	DATA_BLOB confounder;

	MD5_CTX md5;
	uint8_t _enc_key[16];
	DATA_BLOB enc_key;

	DATA_BLOB enc_buffer;

	uint32_t crc32_calc;

	/*
	 * users with rid == 0 should not exist
	 */
	if (rid_crypt && rid == 0) {
		return WERR_DS_DRA_INVALID_PARAMETER;
	}

	/*
	 * The following rid_crypt obfuscation isn't session specific
	 * and not really needed here, because we allways know the rid of the
	 * user account.
	 *
	 * some attributes with this 'additional encryption' include
	 * dBCSPwd, unicodePwd, ntPwdHistory, lmPwdHistory
	 *
	 * But for the rest of samba it's easier when we remove this static
	 * obfuscation here
	 */
	if (rid_crypt) {
		uint32_t i, num_hashes;
		rid_crypt_out = data_blob_talloc(mem_ctx, in->data, in->length);
		W_ERROR_HAVE_NO_MEMORY(rid_crypt_out.data);

		if ((rid_crypt_out.length % 16) != 0) {
			return WERR_DS_DRA_INVALID_PARAMETER;
		}

		num_hashes = rid_crypt_out.length / 16;
		for (i = 0; i < num_hashes; i++) {
			uint32_t offset = i * 16;
			sam_rid_crypt(rid, in->data + offset, rid_crypt_out.data + offset, 1);
		}
		in = &rid_crypt_out;
	}

	/* 
	 * the first 16 bytes at the beginning are the confounder
	 * followed by the 4 byte crc32 checksum
	 */

	enc_buffer = data_blob_talloc(mem_ctx, NULL, in->length+20);
	if (!enc_buffer.data) {
		talloc_free(rid_crypt_out.data);
		return WERR_NOMEM;
	};
	
	confounder = data_blob_const(enc_buffer.data, 16);
	generate_random_buffer(confounder.data, confounder.length);

	/* 
	 * build the encryption key md5 over the session key followed
	 * by the confounder
	 * 
	 * here the gensec session key is used and
	 * not the dcerpc ncacn_ip_tcp "SystemLibraryDTC" key!
	 */
	enc_key = data_blob_const(_enc_key, sizeof(_enc_key));
	MD5Init(&md5);
	MD5Update(&md5, gensec_skey->data, gensec_skey->length);
	MD5Update(&md5, confounder.data, confounder.length);
	MD5Final(enc_key.data, &md5);

	/* 
	 * the first 4 byte are the crc32 checksum
	 * of the remaining bytes
	 */
	crc32_calc = crc32_calc_buffer(in->data, in->length);
	SIVAL(enc_buffer.data, 16, crc32_calc);

	/*
	 * copy the plain buffer part and 
	 * encrypt it using the created encryption key using arcfour
	 */
	memcpy(enc_buffer.data+20, in->data, in->length); 
	talloc_free(rid_crypt_out.data);

	arcfour_crypt_blob(enc_buffer.data+16, enc_buffer.length-16, &enc_key);

	*out = enc_buffer;

	return WERR_OK;
}
Exemple #8
0
BOOL create_next_pdu(pipes_struct *p)
{
	RPC_HDR_RESP hdr_resp;
	BOOL auth_verify = ((p->ntlmssp_chal_flags & NTLMSSP_NEGOTIATE_SIGN) != 0);
	BOOL auth_seal   = ((p->ntlmssp_chal_flags & NTLMSSP_NEGOTIATE_SEAL) != 0);
	uint32 ss_padding_len = 0;
	uint32 data_len;
	uint32 data_space_available;
	uint32 data_len_left;
	prs_struct outgoing_pdu;
	uint32 data_pos;

	/*
	 * If we're in the fault state, keep returning fault PDU's until
	 * the pipe gets closed. JRA.
	 */

	if(p->fault_state) {
		setup_fault_pdu(p, NT_STATUS(0x1c010002));
		return True;
	}

	memset((char *)&hdr_resp, '\0', sizeof(hdr_resp));

	/* Change the incoming request header to a response. */
	p->hdr.pkt_type = RPC_RESPONSE;

	/* Set up rpc header flags. */
	if (p->out_data.data_sent_length == 0) {
		p->hdr.flags = RPC_FLG_FIRST;
	} else {
		p->hdr.flags = 0;
	}

	/*
	 * Work out how much we can fit in a single PDU.
	 */

	data_space_available = sizeof(p->out_data.current_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN;
	if(p->ntlmssp_auth_validated) {
		data_space_available -= (RPC_HDR_AUTH_LEN + RPC_AUTH_NTLMSSP_CHK_LEN);
	} else if(p->netsec_auth_validated) {
		data_space_available -= (RPC_HDR_AUTH_LEN + RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN);
	}

	/*
	 * The amount we send is the minimum of the available
	 * space and the amount left to send.
	 */

	data_len_left = prs_offset(&p->out_data.rdata) - p->out_data.data_sent_length;

	/*
	 * Ensure there really is data left to send.
	 */

	if(!data_len_left) {
		DEBUG(0,("create_next_pdu: no data left to send !\n"));
		return False;
	}

	data_len = MIN(data_len_left, data_space_available);

	/*
	 * Set up the alloc hint. This should be the data left to
	 * send.
	 */

	hdr_resp.alloc_hint = data_len_left;

	/*
	 * Work out if this PDU will be the last.
	 */

	if(p->out_data.data_sent_length + data_len >= prs_offset(&p->out_data.rdata)) {
		p->hdr.flags |= RPC_FLG_LAST;
		if ((auth_seal || auth_verify) && (data_len_left % 8)) {
			ss_padding_len = 8 - (data_len_left % 8);
			DEBUG(10,("create_next_pdu: adding sign/seal padding of %u\n",
				ss_padding_len ));
		}
	}

	/*
	 * Set up the header lengths.
	 */

	if (p->ntlmssp_auth_validated) {
		p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN +
			data_len + ss_padding_len +
			RPC_HDR_AUTH_LEN + RPC_AUTH_NTLMSSP_CHK_LEN;
		p->hdr.auth_len = RPC_AUTH_NTLMSSP_CHK_LEN;
	} else if (p->netsec_auth_validated) {
		p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN +
			data_len + ss_padding_len +
			RPC_HDR_AUTH_LEN + RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN;
		p->hdr.auth_len = RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN;
	} else {
		p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len;
		p->hdr.auth_len = 0;
	}

	/*
	 * Init the parse struct to point at the outgoing
	 * data.
	 */

	prs_init( &outgoing_pdu, 0, p->mem_ctx, MARSHALL);
	prs_give_memory( &outgoing_pdu, (char *)p->out_data.current_pdu, sizeof(p->out_data.current_pdu), False);

	/* Store the header in the data stream. */
	if(!smb_io_rpc_hdr("hdr", &p->hdr, &outgoing_pdu, 0)) {
		DEBUG(0,("create_next_pdu: failed to marshall RPC_HDR.\n"));
		prs_mem_free(&outgoing_pdu);
		return False;
	}

	if(!smb_io_rpc_hdr_resp("resp", &hdr_resp, &outgoing_pdu, 0)) {
		DEBUG(0,("create_next_pdu: failed to marshall RPC_HDR_RESP.\n"));
		prs_mem_free(&outgoing_pdu);
		return False;
	}

	/* Store the current offset. */
	data_pos = prs_offset(&outgoing_pdu);

	/* Copy the data into the PDU. */

	if(!prs_append_some_prs_data(&outgoing_pdu, &p->out_data.rdata, p->out_data.data_sent_length, data_len)) {
		DEBUG(0,("create_next_pdu: failed to copy %u bytes of data.\n", (unsigned int)data_len));
		prs_mem_free(&outgoing_pdu);
		return False;
	}

	/* Copy the sign/seal padding data. */
	if (ss_padding_len) {
		char pad[8];
		memset(pad, '\0', 8);
		if (!prs_copy_data_in(&outgoing_pdu, pad, ss_padding_len)) {
			DEBUG(0,("create_next_pdu: failed to add %u bytes of pad data.\n", (unsigned int)ss_padding_len));
			prs_mem_free(&outgoing_pdu);
			return False;
		}
	}

	if (p->ntlmssp_auth_validated) {
		/*
		 * NTLMSSP processing. Mutually exclusive with Schannel.
		 */
		uint32 crc32 = 0;
		char *data;

		DEBUG(5,("create_next_pdu: sign: %s seal: %s data %d auth %d\n",
			 BOOLSTR(auth_verify), BOOLSTR(auth_seal), data_len + ss_padding_len, p->hdr.auth_len));

		/*
		 * Set data to point to where we copied the data into.
		 */

		data = prs_data_p(&outgoing_pdu) + data_pos;

		if (auth_seal) {
			crc32 = crc32_calc_buffer(data, data_len + ss_padding_len);
			NTLMSSPcalc_p(p, (uchar*)data, data_len + ss_padding_len);
		}

		if (auth_seal || auth_verify) {
			RPC_HDR_AUTH auth_info;

			init_rpc_hdr_auth(&auth_info, NTLMSSP_AUTH_TYPE,
					auth_seal ? RPC_PIPE_AUTH_SEAL_LEVEL : RPC_PIPE_AUTH_SIGN_LEVEL,
					(auth_verify ? ss_padding_len : 0), (auth_verify ? 1 : 0));
			if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, &outgoing_pdu, 0)) {
				DEBUG(0,("create_next_pdu: failed to marshall RPC_HDR_AUTH.\n"));
				prs_mem_free(&outgoing_pdu);
				return False;
			}
		}

		if (auth_verify) {
			RPC_AUTH_NTLMSSP_CHK ntlmssp_chk;
			char *auth_data = prs_data_p(&outgoing_pdu);

			p->ntlmssp_seq_num++;
			init_rpc_auth_ntlmssp_chk(&ntlmssp_chk, NTLMSSP_SIGN_VERSION,
					crc32, p->ntlmssp_seq_num++);
			auth_data = prs_data_p(&outgoing_pdu) + prs_offset(&outgoing_pdu) + 4;
			if(!smb_io_rpc_auth_ntlmssp_chk("auth_sign", &ntlmssp_chk, &outgoing_pdu, 0)) {
				DEBUG(0,("create_next_pdu: failed to marshall RPC_AUTH_NTLMSSP_CHK.\n"));
				prs_mem_free(&outgoing_pdu);
				return False;
			}
			NTLMSSPcalc_p(p, (uchar*)auth_data, RPC_AUTH_NTLMSSP_CHK_LEN - 4);
		}
	} else if (p->netsec_auth_validated) {
		/*
		 * Schannel processing. Mutually exclusive with NTLMSSP.
		 */
		int auth_type, auth_level;
		char *data;
		RPC_HDR_AUTH auth_info;

		RPC_AUTH_NETSEC_CHK verf;
		prs_struct rverf;
		prs_struct rauth;

		data = prs_data_p(&outgoing_pdu) + data_pos;
		/* Check it's the type of reply we were expecting to decode */

		get_auth_type_level(p->netsec_auth.auth_flags, &auth_type, &auth_level);
		init_rpc_hdr_auth(&auth_info, auth_type, auth_level, 
				  ss_padding_len, 1);

		if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, &outgoing_pdu, 0)) {
			DEBUG(0,("create_next_pdu: failed to marshall RPC_HDR_AUTH.\n"));
			prs_mem_free(&outgoing_pdu);
			return False;
		}

		prs_init(&rverf, 0, p->mem_ctx, MARSHALL);
		prs_init(&rauth, 0, p->mem_ctx, MARSHALL);

		netsec_encode(&p->netsec_auth, 
			      p->netsec_auth.auth_flags,
			      SENDER_IS_ACCEPTOR,
			      &verf, data, data_len + ss_padding_len);

		smb_io_rpc_auth_netsec_chk("", RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN, 
			&verf, &outgoing_pdu, 0);

		p->netsec_auth.seq_num++;
	}

	/*
	 * Setup the counts for this PDU.
	 */

	p->out_data.data_sent_length += data_len;
	p->out_data.current_pdu_len = p->hdr.frag_len;
	p->out_data.current_pdu_sent = 0;

	prs_mem_free(&outgoing_pdu);
	return True;
}
Exemple #9
0
DATA_BLOB decrypt_drsuapi_blob(TALLOC_CTX *mem_ctx,
			       const DATA_BLOB *session_key,
			       bool rcrypt,
			       uint32_t rid,
			       const DATA_BLOB *buffer)
{
	DATA_BLOB confounder;
	DATA_BLOB enc_buffer;

	struct MD5Context md5;
	uint8_t _enc_key[16];
	DATA_BLOB enc_key;

	DATA_BLOB dec_buffer;

	uint32_t crc32_given;
	uint32_t crc32_calc;
	DATA_BLOB checked_buffer;

	DATA_BLOB plain_buffer;

	/*
	 * the combination "c[3] s[1] e[1] d[0]..."
	 * was successful!!!!!!!!!!!!!!!!!!!!!!!!!!
	 */

	/*
	 * the first 16 bytes at the beginning are the confounder
	 * followed by the 4 byte crc32 checksum
	 */
	if (buffer->length < 20) {
		return data_blob_const(NULL, 0);
	}
	confounder = data_blob_const(buffer->data, 16);
	enc_buffer = data_blob_const(buffer->data + 16, buffer->length - 16);

	/*
	 * build the encryption key md5 over the session key followed
	 * by the confounder
	 *
	 * here the gensec session key is used and
	 * not the dcerpc ncacn_ip_tcp "SystemLibraryDTC" key!
	 */
	enc_key = data_blob_const(_enc_key, sizeof(_enc_key));
	MD5Init(&md5);
	MD5Update(&md5, session_key->data, session_key->length);
	MD5Update(&md5, confounder.data, confounder.length);
	MD5Final(enc_key.data, &md5);

	/*
	 * copy the encrypted buffer part and
	 * decrypt it using the created encryption key using arcfour
	 */
	dec_buffer = data_blob_talloc(mem_ctx, enc_buffer.data, enc_buffer.length);
	if (!dec_buffer.data) {
		return data_blob_const(NULL, 0);
	}
	SamOEMhashBlob(dec_buffer.data, dec_buffer.length, &enc_key);

	/*
	 * the first 4 byte are the crc32 checksum
	 * of the remaining bytes
	 */
	crc32_given = IVAL(dec_buffer.data, 0);
	crc32_calc = crc32_calc_buffer((const char *)dec_buffer.data + 4 , dec_buffer.length - 4);
	if (crc32_given != crc32_calc) {
		DEBUG(1,("CRC32: given[0x%08X] calc[0x%08X]\n",
		      crc32_given, crc32_calc));
		return data_blob_const(NULL, 0);
	}
	checked_buffer = data_blob_talloc(mem_ctx, dec_buffer.data + 4, dec_buffer.length - 4);
	if (!checked_buffer.data) {
		return data_blob_const(NULL, 0);
	}

	/*
	 * some attributes seem to be in a usable form after this decryption
	 * (supplementalCredentials, priorValue, currentValue, trustAuthOutgoing,
	 *  trustAuthIncoming, initialAuthOutgoing, initialAuthIncoming)
	 * At least supplementalCredentials contains plaintext
	 * like "Primary:Kerberos" (in unicode form)
	 *
	 * some attributes seem to have some additional encryption
	 * dBCSPwd, unicodePwd, ntPwdHistory, lmPwdHistory
	 *
	 * it's the sam_rid_crypt() function, as the value is constant,
	 * so it doesn't depend on sessionkeys.
	 */
	if (rcrypt) {
		uint32_t i, num_hashes;

		if ((checked_buffer.length % 16) != 0) {
			return data_blob_const(NULL, 0);
		}

		plain_buffer = data_blob_talloc(mem_ctx, checked_buffer.data, checked_buffer.length);
		if (!plain_buffer.data) {
			return data_blob_const(NULL, 0);
		}

		num_hashes = plain_buffer.length / 16;
		for (i = 0; i < num_hashes; i++) {
			uint32_t offset = i * 16;
			sam_pwd_hash(rid, checked_buffer.data + offset, plain_buffer.data + offset, 0);
		}
	} else {
		plain_buffer = checked_buffer;
	}

	return plain_buffer;
}
Exemple #10
0
static NTSTATUS ntlmssp_make_packet_signature(NTLMSSP_STATE *ntlmssp_state,
						const uchar *data, size_t length, 
						const uchar *whole_pdu, size_t pdu_length,
						enum ntlmssp_direction direction,
						DATA_BLOB *sig,
						bool encrypt_sig)
{
	if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
		HMACMD5Context ctx;
		uchar seq_num[4];
		uchar digest[16];

		*sig = data_blob(NULL, NTLMSSP_SIG_SIZE);
		if (!sig->data) {
			return NT_STATUS_NO_MEMORY;
		}

		switch (direction) {
			case NTLMSSP_SEND:
	                        DEBUG(100,("ntlmssp_make_packet_signature: SEND seq = %u, len = %u, pdu_len = %u\n",
					ntlmssp_state->ntlm2_send_seq_num,
					(unsigned int)length,
					(unsigned int)pdu_length));

				SIVAL(seq_num, 0, ntlmssp_state->ntlm2_send_seq_num);
				ntlmssp_state->ntlm2_send_seq_num++;
				hmac_md5_init_limK_to_64(ntlmssp_state->send_sign_key, 16, &ctx);
				break;
			case NTLMSSP_RECEIVE:

				DEBUG(100,("ntlmssp_make_packet_signature: RECV seq = %u, len = %u, pdu_len = %u\n",
					ntlmssp_state->ntlm2_recv_seq_num,
					(unsigned int)length,
					(unsigned int)pdu_length));

				SIVAL(seq_num, 0, ntlmssp_state->ntlm2_recv_seq_num);
				ntlmssp_state->ntlm2_recv_seq_num++;
				hmac_md5_init_limK_to_64(ntlmssp_state->recv_sign_key, 16, &ctx);
				break;
                }

		dump_data_pw("pdu data ", whole_pdu, pdu_length);

		hmac_md5_update(seq_num, 4, &ctx);
		hmac_md5_update(whole_pdu, pdu_length, &ctx);
		hmac_md5_final(digest, &ctx);

		if (encrypt_sig && (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH)) {
			switch (direction) {
			case NTLMSSP_SEND:
				arcfour_crypt_sbox(&ntlmssp_state->send_seal_arc4_state, digest, 8);
				break;
			case NTLMSSP_RECEIVE:
				arcfour_crypt_sbox(&ntlmssp_state->recv_seal_arc4_state, digest, 8);
				break;
			}
		}

		SIVAL(sig->data, 0, NTLMSSP_SIGN_VERSION);
		memcpy(sig->data + 4, digest, 8);
		memcpy(sig->data + 12, seq_num, 4);

		dump_data_pw("ntlmssp v2 sig ", sig->data, sig->length);

	} else {
		uint32 crc;
		crc = crc32_calc_buffer(data, length);
		if (!msrpc_gen(sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, ntlmssp_state->ntlmv1_seq_num)) {
			return NT_STATUS_NO_MEMORY;
		}
		
		ntlmssp_state->ntlmv1_seq_num++;

		dump_arc4_state("ntlmssp hash: \n", &ntlmssp_state->ntlmv1_arc4_state);
		arcfour_crypt_sbox(&ntlmssp_state->ntlmv1_arc4_state, sig->data+4, sig->length-4);
	}
	return NT_STATUS_OK;
}
Exemple #11
0
int plf_check_crc(int fileIdx, int sectIdx)
{
    u32 crc_accum = 0;
    u32 crc_num_size = 0;
    s_plf_section_entry* section;
    s_plf_file_entry* fileEntry;

    PLF_VERIFY_IDX(fileIdx);

    section = plf_int_get_section(fileIdx, sectIdx);
    fileEntry = &plf_files[fileIdx];

    if (section == 0)
        return PLF_E_PARAM;

    if (fileEntry->fildes == -1)
    {
        // Buffer case

        crc32_calc_buffer(&crc_accum, &crc_num_size, (((u8*) fileEntry->buffer)
                + section->offset), section->hdr.dwSectionSize);
        crc32_calc_dw(&crc_accum, &crc_num_size);
    }
    else
    {
        // File case.. we need to read the contents of the file
        u8* tmpBuf = (u8*) malloc(0x1000);

        if (tmpBuf == 0)
            return PLF_E_MEM;

        u32 bytes_remaining = section->hdr.dwSectionSize;

        while (bytes_remaining > 0)
        {
            u32 read_len;
            if (bytes_remaining > 0x1000)
            {
                read_len = 0x1000;
            }
            else
            {
                read_len = bytes_remaining;
            }

            u32 offset = section->hdr.dwSectionSize - bytes_remaining;

            u32 bytes_read = plf_get_payload_raw(fileIdx, sectIdx, tmpBuf,
                    offset, read_len);
            if (bytes_read < 0)
            {
                free(tmpBuf);
                return bytes_read;
            }

            crc32_calc_buffer(&crc_accum, &crc_num_size, tmpBuf, read_len);

            bytes_remaining -= read_len;

        }

        // finish crc
        free(tmpBuf);
        crc32_calc_dw(&crc_accum, &crc_num_size);

    }

    if (crc_accum == section->hdr.dwCRC32)
        return 0;
    else
        return PLF_E_CRC;

}