summaryrefslogtreecommitdiff
path: root/source4/torture/nbt/dgram.c
blob: c5a3b61136a47dfb64b14e51bc352efe4303f819 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/* 
   Unix SMB/CIFS implementation.

   NBT dgram testing

   Copyright (C) Andrew Tridgell 2005
   
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "includes.h"
#include "libcli/nbt/libnbt.h"
#include "libcli/dgram/libdgram.h"
#include "librpc/gen_ndr/ndr_nbt.h"
#include "lib/socket/socket.h"
#include "lib/events/events.h"

#define TEST_NAME "TORTURE_TEST"

/*
  reply handler for netlogon request
*/
static void netlogon_handler(struct dgram_mailslot_handler *dgmslot, 
			     struct nbt_dgram_packet *packet, 
			     const char *src_address, int src_port)
{
	NTSTATUS status;
	struct nbt_netlogon_packet netlogon;
	int *replies = dgmslot->private;

	printf("netlogon reply from %s:%d\n", src_address, src_port);

	status = dgram_mailslot_netlogon_parse(dgmslot, dgmslot, packet, &netlogon);
	if (!NT_STATUS_IS_OK(status)) {
		printf("Failed to parse netlogon packet from %s:%d\n",
		       src_address, src_port);
		return;
	}

	NDR_PRINT_DEBUG(nbt_netlogon_packet, &netlogon);

	(*replies)++;
}


/* test UDP/138 netlogon requests */
static BOOL nbt_test_netlogon(TALLOC_CTX *mem_ctx, 
			      struct nbt_name name, const char *address)
{
	struct dgram_mailslot_handler *dgmslot;
	struct nbt_dgram_socket *dgmsock = nbt_dgram_socket_init(mem_ctx, NULL);
	const char *myaddress = talloc_strdup(mem_ctx, iface_best_ip(address));
	struct nbt_netlogon_packet logon;
	struct nbt_name myname;
	NTSTATUS status;
	struct timeval tv = timeval_current();
	int replies = 0;

	/* try receiving replies on port 138 first, which will only
	   work if we are root and smbd/nmbd are not running - fall
	   back to listening on any port, which means replies from
	   some windows versions won't be seen */
	status = socket_listen(dgmsock->sock, myaddress, lp_dgram_port(), 0, 0);
	if (!NT_STATUS_IS_OK(status)) {
		socket_listen(dgmsock->sock, myaddress, 0, 0, 0);
	}

	/* setup a temporary mailslot listener for replies */
	dgmslot = dgram_mailslot_temp(dgmsock, NBT_MAILSLOT_GETDC,
				      netlogon_handler, &replies);
	

	ZERO_STRUCT(logon);
	logon.command = NETLOGON_QUERY_FOR_PDC;
	logon.req.pdc.computer_name = TEST_NAME;
	logon.req.pdc.mailslot_name = dgmslot->mailslot_name;
	logon.req.pdc.unicode_name  = TEST_NAME;
	logon.req.pdc.nt_version    = 1;
	logon.req.pdc.lmnt_token    = 0xFFFF;
	logon.req.pdc.lm20_token    = 0xFFFF;

	myname.name = TEST_NAME;
	myname.type = NBT_NAME_CLIENT;
	myname.scope = NULL;

	status = dgram_mailslot_netlogon_send(dgmsock, &name, address, &myname, &logon);
	if (!NT_STATUS_IS_OK(status)) {
		printf("Failed to send netlogon request - %s\n", nt_errstr(status));
		goto failed;
	}


	while (timeval_elapsed(&tv) < 5 && replies == 0) {
		event_loop_once(dgmsock->event_ctx);
	}

	talloc_free(dgmsock);
	return True;

failed:
	talloc_free(dgmsock);
	return False;
}


/*
  test nbt dgram operations
*/
BOOL torture_nbt_dgram(void)
{
	const char *address;
	struct nbt_name name;
	TALLOC_CTX *mem_ctx = talloc_new(NULL);
	NTSTATUS status;
	BOOL ret = True;
	
	name.name = lp_parm_string(-1, "torture", "host");
	name.type = NBT_NAME_PDC;
	name.scope = NULL;

	/* do an initial name resolution to find its IP */
	status = resolve_name(&name, mem_ctx, &address);
	if (!NT_STATUS_IS_OK(status)) {
		printf("Failed to resolve %s - %s\n",
		       name.name, nt_errstr(status));
		talloc_free(mem_ctx);
		return False;
	}

	ret &= nbt_test_netlogon(mem_ctx, name, address);

	talloc_free(mem_ctx);

	return ret;
}