Exemplo n.º 1
0
bool receive_getdc_response(TALLOC_CTX *mem_ctx,
			    struct sockaddr_storage *dc_ss,
			    const char *domain_name,
			    uint32_t *nt_version,
			    const char **dc_name,
			    struct netlogon_samlogon_response **_r)
{
	struct packet_struct *packet;
	const char *my_mailslot = NULL;
	struct in_addr dc_ip;
	DATA_BLOB blob;
	struct netlogon_samlogon_response r;
	union dgram_message_body p;
	enum ndr_err_code ndr_err;
	NTSTATUS status;

	const char *returned_dc = NULL;
	const char *returned_domain = NULL;

	if (dc_ss->ss_family != AF_INET) {
		return false;
	}

	dc_ip = ((struct sockaddr_in *)dc_ss)->sin_addr;

	my_mailslot = mailslot_name(mem_ctx, dc_ip);
	if (!my_mailslot) {
		return false;
	}

	packet = receive_unexpected(DGRAM_PACKET, 0, my_mailslot);

	if (packet == NULL) {
		DEBUG(5, ("Did not receive packet for %s\n", my_mailslot));
		return False;
	}

	DEBUG(5, ("Received packet for %s\n", my_mailslot));

	blob = data_blob_const(packet->packet.dgram.data,
			       packet->packet.dgram.datasize);

	if (blob.length < 4) {
		DEBUG(0,("invalid length: %d\n", (int)blob.length));
		return false;
	}

	if (RIVAL(blob.data,0) != DGRAM_SMB) {
		DEBUG(0,("invalid packet\n"));
		return false;
	}

	blob.data += 4;
	blob.length -= 4;

	ndr_err = ndr_pull_union_blob_all(&blob, mem_ctx, &p, DGRAM_SMB,
		       (ndr_pull_flags_fn_t)ndr_pull_dgram_smb_packet);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		DEBUG(0,("failed to parse packet\n"));
		return false;
	}

	if (p.smb.smb_command != SMB_TRANSACTION) {
		DEBUG(0,("invalid smb_command: %d\n", p.smb.smb_command));
		return false;
	}

	if (DEBUGLEVEL >= 10) {
		NDR_PRINT_DEBUG(dgram_smb_packet, &p);
	}

	blob = p.smb.body.trans.data;

	ZERO_STRUCT(r);

	status = pull_netlogon_samlogon_response(&blob, mem_ctx, &r);
	if (!NT_STATUS_IS_OK(status)) {
		return false;
	}

	map_netlogon_samlogon_response(&r);

	/* do we still need this ? */
	*nt_version = r.ntver;

	returned_domain = r.data.nt5_ex.domain;
	returned_dc = r.data.nt5_ex.pdc_name;

	if (!strequal(returned_domain, domain_name)) {
		DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
			  domain_name, returned_domain));
		return false;
	}

	*dc_name = talloc_strdup(mem_ctx, returned_dc);
	if (!*dc_name) {
		return false;
	}

	if (**dc_name == '\\')	*dc_name += 1;
	if (**dc_name == '\\')	*dc_name += 1;

	if (_r) {
		*_r = (struct netlogon_samlogon_response *)talloc_memdup(
			mem_ctx, &r, sizeof(struct netlogon_samlogon_response));
		if (!*_r) {
			return false;
		}
	}

	DEBUG(10, ("GetDC gave name %s for domain %s\n",
		   *dc_name, returned_domain));

	return True;
}
Exemplo n.º 2
0
bool pull_mailslot_cldap_reply(TALLOC_CTX *mem_ctx,
			       const DATA_BLOB *blob,
			       union nbt_cldap_netlogon *r,
			       uint32_t *nt_version)
{
	enum ndr_err_code ndr_err;
	uint32_t nt_version_query = ((*nt_version) & 0x0000001f);
	uint16_t command = 0;

	ndr_err = ndr_pull_struct_blob(blob, mem_ctx, &command,
			(ndr_pull_flags_fn_t)ndr_pull_uint16);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		return false;
	}

	switch (command) {
		case 0x13: /* 19 */
		case 0x15: /* 21 */
		case 0x17: /* 23 */
		case 0x19: /* 25 */
			 break;
		default:
			DEBUG(1,("got unexpected command: %d (0x%08x)\n",
				command, command));
			return false;
	}

	ndr_err = ndr_pull_union_blob_all(blob, mem_ctx, r, nt_version_query,
		       (ndr_pull_flags_fn_t)ndr_pull_nbt_cldap_netlogon);
	if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		goto done;
	}

	/* when the caller requested just those nt_version bits that the server
	 * was able to reply to, we are fine and all done. otherwise we need to
	 * assume downgraded replies which are painfully parsed here - gd */

	if (nt_version_query & NETLOGON_VERSION_WITH_CLOSEST_SITE) {
		nt_version_query &= ~NETLOGON_VERSION_WITH_CLOSEST_SITE;
	}
	ndr_err = ndr_pull_union_blob_all(blob, mem_ctx, r, nt_version_query,
		       (ndr_pull_flags_fn_t)ndr_pull_nbt_cldap_netlogon);
	if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		goto done;
	}
	if (nt_version_query & NETLOGON_VERSION_5EX_WITH_IP) {
		nt_version_query &= ~NETLOGON_VERSION_5EX_WITH_IP;
	}
	ndr_err = ndr_pull_union_blob_all(blob, mem_ctx, r, nt_version_query,
		       (ndr_pull_flags_fn_t)ndr_pull_nbt_cldap_netlogon);
	if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		goto done;
	}
	if (nt_version_query & NETLOGON_VERSION_5EX) {
		nt_version_query &= ~NETLOGON_VERSION_5EX;
	}
	ndr_err = ndr_pull_union_blob_all(blob, mem_ctx, r, nt_version_query,
		       (ndr_pull_flags_fn_t)ndr_pull_nbt_cldap_netlogon);
	if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		goto done;
	}
	if (nt_version_query & NETLOGON_VERSION_5) {
		nt_version_query &= ~NETLOGON_VERSION_5;
	}
	ndr_err = ndr_pull_union_blob_all(blob, mem_ctx, r, nt_version_query,
		       (ndr_pull_flags_fn_t)ndr_pull_nbt_cldap_netlogon);
	if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		goto done;
	}

	return false;

 done:
	if (DEBUGLEVEL >= 10) {
		NDR_PRINT_UNION_DEBUG(nbt_cldap_netlogon, nt_version_query, r);
	}

	*nt_version = nt_version_query;

	return true;
}
Exemplo n.º 3
0
static bool parse_getdc_response(
	struct packet_struct *packet,
	TALLOC_CTX *mem_ctx,
	const char *domain_name,
	uint32_t *nt_version,
	const char **dc_name,
	struct netlogon_samlogon_response **samlogon_response)
{
	DATA_BLOB blob;
	struct netlogon_samlogon_response *r;
	union dgram_message_body p;
	enum ndr_err_code ndr_err;
	NTSTATUS status;

	const char *returned_dc = NULL;
	const char *returned_domain = NULL;

	blob = data_blob_const(packet->packet.dgram.data,
			       packet->packet.dgram.datasize);
	if (blob.length < 4) {
		DEBUG(1, ("invalid length: %d\n", (int)blob.length));
		return false;
	}

	if (RIVAL(blob.data,0) != DGRAM_SMB) {
		DEBUG(1, ("invalid packet\n"));
		return false;
	}

	blob.data += 4;
	blob.length -= 4;

	ndr_err = ndr_pull_union_blob_all(&blob, mem_ctx, &p, DGRAM_SMB,
		       (ndr_pull_flags_fn_t)ndr_pull_dgram_smb_packet);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		DEBUG(1, ("failed to parse packet\n"));
		return false;
	}

	if (p.smb.smb_command != SMB_TRANSACTION) {
		DEBUG(1, ("invalid smb_command: %d\n", p.smb.smb_command));
		return false;
	}

	if (DEBUGLEVEL >= 10) {
		NDR_PRINT_DEBUG(dgram_smb_packet, &p);
	}

	blob = p.smb.body.trans.data;

	r = talloc_zero(mem_ctx, struct netlogon_samlogon_response);
	if (!r) {
		return false;
	}

	status = pull_netlogon_samlogon_response(&blob, r, r);
	if (!NT_STATUS_IS_OK(status)) {
		TALLOC_FREE(r);
		return false;
	}

	map_netlogon_samlogon_response(r);

	/* do we still need this ? */
	*nt_version = r->ntver;

	returned_domain = r->data.nt5_ex.domain_name;
	returned_dc = r->data.nt5_ex.pdc_name;

	if (!strequal(returned_domain, domain_name)) {
		DEBUG(3, ("GetDC: Expected domain %s, got %s\n",
			  domain_name, returned_domain));
		TALLOC_FREE(r);
		return false;
	}

	if (*returned_dc == '\\') returned_dc += 1;
	if (*returned_dc == '\\') returned_dc += 1;

	*dc_name = talloc_strdup(mem_ctx, returned_dc);
	if (!*dc_name) {
		TALLOC_FREE(r);
		return false;
	}

	if (samlogon_response) {
		*samlogon_response = r;
	} else {
		TALLOC_FREE(r);
	}

	DEBUG(10, ("GetDC gave name %s for domain %s\n",
		   *dc_name, returned_domain));

	return True;
}