예제 #1
0
WERROR decode_wkssvc_join_password_buffer(TALLOC_CTX *mem_ctx,
					  struct wkssvc_PasswordBuffer *pwd_buf,
					  DATA_BLOB *session_key,
					  char **pwd)
{
	uint8_t buffer[516];
	struct MD5Context ctx;
	uint32_t pwd_len;

	DATA_BLOB confounded_session_key;

	int confounder_len = 8;
	uint8_t confounder[8];

	*pwd = NULL;

	if (!pwd_buf) {
		return WERR_BAD_PASSWORD;
	}

	if (session_key->length != 16) {
		DEBUG(10,("invalid session key\n"));
		return WERR_BAD_PASSWORD;
	}

	confounded_session_key = data_blob_talloc(mem_ctx, NULL, 16);

	memcpy(&confounder, &pwd_buf->data[0], confounder_len);
	memcpy(&buffer, &pwd_buf->data[8], 516);

	MD5Init(&ctx);
	MD5Update(&ctx, session_key->data, session_key->length);
	MD5Update(&ctx, confounder, confounder_len);
	MD5Final(confounded_session_key.data, &ctx);

	SamOEMhashBlob(buffer, 516, &confounded_session_key);

	if (!decode_pw_buffer(mem_ctx, buffer, pwd, &pwd_len, STR_UNICODE)) {
		data_blob_free(&confounded_session_key);
		return WERR_BAD_PASSWORD;
	}

	data_blob_free(&confounded_session_key);

	return WERR_OK;
}
예제 #2
0
void encode_wkssvc_join_password_buffer(TALLOC_CTX *mem_ctx,
					const char *pwd,
					DATA_BLOB *session_key,
					struct wkssvc_PasswordBuffer **pwd_buf)
{
	uint8_t buffer[516];
	struct MD5Context ctx;
	struct wkssvc_PasswordBuffer *my_pwd_buf = NULL;
	DATA_BLOB confounded_session_key;
	int confounder_len = 8;
	uint8_t confounder[8];

	my_pwd_buf = talloc_zero(mem_ctx, struct wkssvc_PasswordBuffer);
	if (!my_pwd_buf) {
		return;
	}

	confounded_session_key = data_blob_talloc(mem_ctx, NULL, 16);

	encode_pw_buffer(buffer, pwd, STR_UNICODE);

	generate_random_buffer((uint8_t *)confounder, confounder_len);

	MD5Init(&ctx);
	MD5Update(&ctx, session_key->data, session_key->length);
	MD5Update(&ctx, confounder, confounder_len);
	MD5Final(confounded_session_key.data, &ctx);

	SamOEMhashBlob(buffer, 516, &confounded_session_key);

	memcpy(&my_pwd_buf->data[0], confounder, confounder_len);
	memcpy(&my_pwd_buf->data[8], buffer, 516);

	data_blob_free(&confounded_session_key);

	*pwd_buf = my_pwd_buf;
}
예제 #3
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;
}
예제 #4
0
파일: net_domain.c 프로젝트: aosm/samba
NTSTATUS netdom_join_domain( TALLOC_CTX *mem_ctx, struct cli_state *cli, 
                           DOM_SID *dom_sid, const char *clear_pw,
                           enum netdom_domain_t dom_type )
{	
	struct rpc_pipe_client *pipe_hnd = NULL;
	POLICY_HND sam_pol, domain_pol, user_pol;
	NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
	char *acct_name;
	const char *const_acct_name;
	uint32 user_rid;
	uint32 num_rids, *name_types, *user_rids;
	uint32 flags = 0x3e8;
	uint32 acb_info = ACB_WSTRUST;
	uint32 acct_flags=0;
	uint32 fields_present;
	uchar pwbuf[532];
	SAM_USERINFO_CTR ctr;
	SAM_USER_INFO_25 p25;
	const int infolevel = 25;
	struct MD5Context md5ctx;
	uchar md5buffer[16];
	DATA_BLOB digested_session_key;
	uchar md4_trust_password[16];

	/* Open the domain */
	
	if ( (pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &status)) == NULL ) {
		DEBUG(0, ("Error connecting to SAM pipe. Error was %s\n",
			nt_errstr(status) ));
		return status;
	}

	status = rpccli_samr_connect(pipe_hnd, mem_ctx, 
			SEC_RIGHTS_MAXIMUM_ALLOWED, &sam_pol);
	if ( !NT_STATUS_IS_OK(status) )
		return status;

	
	status = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &sam_pol,
			SEC_RIGHTS_MAXIMUM_ALLOWED, dom_sid, &domain_pol);
	if ( !NT_STATUS_IS_OK(status) )
		return status;

	/* Create domain user */
	
	acct_name = talloc_asprintf(mem_ctx, "%s$", global_myname()); 
	strlower_m(acct_name);
	const_acct_name = acct_name;

	/* Don't try to set any acb_info flags other than ACB_WSTRUST */

        acct_flags = SAMR_GENERIC_READ | SAMR_GENERIC_WRITE |
                SAMR_GENERIC_EXECUTE | SAMR_STANDARD_WRITEDAC |
                SAMR_STANDARD_DELETE | SAMR_USER_SETPASS | SAMR_USER_GETATTR |
                SAMR_USER_SETATTR;
	DEBUG(10, ("Creating account with flags: %d\n",acct_flags));
	status = rpccli_samr_create_dom_user(pipe_hnd, mem_ctx, &domain_pol,
			acct_name, acb_info, acct_flags, &user_pol, &user_rid);

	if ( !NT_STATUS_IS_OK(status) 
		&& !NT_STATUS_EQUAL(status, NT_STATUS_USER_EXISTS)) 
	{
		d_fprintf(stderr, "Creation of workstation account failed\n");

		/* If NT_STATUS_ACCESS_DENIED then we have a valid
		   username/password combo but the user does not have
		   administrator access. */

		if (NT_STATUS_V(status) == NT_STATUS_V(NT_STATUS_ACCESS_DENIED))
			d_fprintf(stderr, "User specified does not have administrator privileges\n");

		return status;
	}

	/* We *must* do this.... don't ask... */

	if (NT_STATUS_IS_OK(status)) {
		rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);
	}

	status = rpccli_samr_lookup_names(pipe_hnd, mem_ctx,
			&domain_pol, flags, 1, &const_acct_name, 
			&num_rids, &user_rids, &name_types);
	if ( !NT_STATUS_IS_OK(status) )
		return status;

	if ( name_types[0] != SID_NAME_USER) {
		DEBUG(0, ("%s is not a user account (type=%d)\n", acct_name, name_types[0]));
		return NT_STATUS_INVALID_WORKSTATION;
	}

	user_rid = user_rids[0];
		
	/* Open handle on user */

	status = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
			SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid, &user_pol);
	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}
	
	/* Create a random machine account password and generate the hash */

	E_md4hash(clear_pw, md4_trust_password);
	encode_pw_buffer(pwbuf, clear_pw, STR_UNICODE);
	
	generate_random_buffer((uint8*)md5buffer, sizeof(md5buffer));
	digested_session_key = data_blob_talloc(mem_ctx, 0, 16);
	
	MD5Init(&md5ctx);
	MD5Update(&md5ctx, md5buffer, sizeof(md5buffer));
	MD5Update(&md5ctx, cli->user_session_key.data, cli->user_session_key.length);
	MD5Final(digested_session_key.data, &md5ctx);
	
	SamOEMhashBlob(pwbuf, sizeof(pwbuf), &digested_session_key);
	memcpy(&pwbuf[516], md5buffer, sizeof(md5buffer));

	/* Fill in the additional account flags now */

	acb_info |= ACB_PWNOEXP;
	if ( dom_type == ND_TYPE_AD ) {
#if !defined(ENCTYPE_ARCFOUR_HMAC)
		acb_info |= ACB_USE_DES_KEY_ONLY;
#endif
		;;
	}

	/* Set password and account flags on machine account */

	ZERO_STRUCT(ctr);
	ZERO_STRUCT(p25);

	fields_present = ACCT_NT_PWD_SET | ACCT_LM_PWD_SET | ACCT_FLAGS;
	init_sam_user_info25P(&p25, fields_present, acb_info, (char *)pwbuf);

	ctr.switch_value = infolevel;
	ctr.info.id25    = &p25;

	status = rpccli_samr_set_userinfo2(pipe_hnd, mem_ctx, &user_pol,
					   infolevel, &cli->user_session_key, &ctr);

	if ( !NT_STATUS_IS_OK(status) ) {
		d_fprintf( stderr, "Failed to set password for machine account (%s)\n", 
			nt_errstr(status));
		return status;
	}

	rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);
	cli_rpc_pipe_close(pipe_hnd); /* Done with this pipe */
	
	return status;
}