22
22
#include "includes.h"
23
#include "torture/torture.h"
24
23
#include "torture/smbtorture.h"
25
24
#include <tevent.h>
26
#include "lib/socket/socket.h"
27
25
#include "lib/stream/packet.h"
28
#include "auth/credentials/credentials.h"
29
#include "torture/rpc/rpc.h"
30
#include "torture/rpc/netlogon.h"
26
#include "lib/tsocket/tsocket.h"
27
#include "libcli/util/tstream.h"
28
#include "torture/rpc/torture_rpc.h"
31
29
#include "../lib/crypto/crypto.h"
32
30
#include "libcli/auth/libcli_auth.h"
33
31
#include "librpc/gen_ndr/ndr_netlogon_c.h"
34
#include "librpc/gen_ndr/ndr_netlogon.h"
35
32
#include "librpc/gen_ndr/ndr_ntp_signd.h"
36
33
#include "param/param.h"
34
#include "system/network.h"
38
36
#define TEST_MACHINE_NAME "ntpsigndtest"
40
struct signd_client_socket {
41
struct socket_context *sock;
44
struct tevent_fd *fde;
38
struct signd_client_state {
39
struct tsocket_address *local_address;
40
struct tsocket_address *remote_address;
42
struct tstream_context *tstream;
43
struct tevent_queue *send_queue;
45
uint8_t request_hdr[4];
46
struct iovec request_iov[2];
47
DATA_BLOB request, reply;
49
struct packet_context *packet;
54
static NTSTATUS signd_client_full_packet(void *private_data, DATA_BLOB data)
56
struct signd_client_socket *signd_client = talloc_get_type(private_data, struct signd_client_socket);
57
talloc_steal(signd_client, data.data);
58
signd_client->reply = data;
59
signd_client->reply.length -= 4;
60
signd_client->reply.data += 4;
64
static void signd_client_error_handler(void *private_data, NTSTATUS status)
66
struct signd_client_socket *signd_client = talloc_get_type(private_data, struct signd_client_socket);
67
signd_client->status = status;
71
handle fd events on a signd_client_socket
73
static void signd_client_socket_handler(struct tevent_context *ev, struct tevent_fd *fde,
74
uint16_t flags, void *private_data)
76
struct signd_client_socket *signd_client = talloc_get_type(private_data, struct signd_client_socket);
77
if (flags & TEVENT_FD_READ) {
78
packet_recv(signd_client->packet);
81
if (flags & TEVENT_FD_WRITE) {
82
packet_queue_run(signd_client->packet);
89
/* A torture test to show that the unix domain socket protocol is
90
* operating correctly, and the signatures are as expected */
92
static bool test_ntp_signd(struct torture_context *tctx,
54
* A torture test to show that the unix domain socket protocol is
55
* operating correctly, and the signatures are as expected
57
static bool test_ntp_signd(struct torture_context *tctx,
93
58
struct dcerpc_pipe *p,
94
59
struct cli_credentials *credentials)
96
61
struct netlogon_creds_CredentialState *creds;
97
62
TALLOC_CTX *mem_ctx = talloc_new(tctx);
100
64
struct netr_ServerReqChallenge r;
101
65
struct netr_ServerAuthenticate3 a;
102
66
struct netr_Credential credentials1, credentials2, credentials3;
151
122
torture_comment(tctx, "Testing ServerAuthenticate3\n");
153
status = dcerpc_netr_ServerAuthenticate3(p, tctx, &a);
154
torture_assert_ntstatus_ok(tctx, status, "ServerAuthenticate3");
155
torture_assert(tctx, netlogon_creds_client_check(creds, &credentials3), "Credential chaining failed");
124
torture_assert_ntstatus_ok(tctx,
125
dcerpc_netr_ServerAuthenticate3_r(p->binding_handle, tctx, &a),
126
"ServerAuthenticate3 failed");
127
torture_assert_ntstatus_ok(tctx, a.out.result,
128
"ServerAuthenticate3 failed");
130
netlogon_creds_client_check(creds, &credentials3),
131
"Credential chaining failed");
157
133
sign_req.op = SIGN_TO_CLIENT;
158
134
sign_req.packet_id = 1;
159
135
sign_req.key_id = rid;
160
136
sign_req.packet_to_sign = data_blob_string_const("I am a tea pot");
162
ndr_err = ndr_push_struct_blob(&sign_req_blob, mem_ctx, NULL, &sign_req, (ndr_push_flags_fn_t)ndr_push_sign_request);
163
torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), "Failed to push sign_req");
165
signd_client = talloc(mem_ctx, struct signd_client_socket);
167
status = socket_create("unix", SOCKET_TYPE_STREAM, &signd_client->sock, 0);
169
signd_socket_address = talloc_asprintf(signd_client, "%s/socket",
170
lp_ntp_signd_socket_directory(tctx->lp_ctx));
172
status = socket_connect_ev(signd_client->sock, NULL,
173
socket_address_from_strings(signd_client,
174
"unix", signd_socket_address, 0), 0, tctx->ev);
175
torture_assert_ntstatus_ok(tctx, status, "Failed to connect to signd!");
177
/* Setup the FDE, start listening for read events
178
* from the start (otherwise we may miss a socket
179
* drop) and mark as AUTOCLOSE along with the fde */
181
/* Ths is equivilant to EVENT_FD_READABLE(signd_client->fde) */
182
signd_client->fde = tevent_add_fd(tctx->ev, signd_client->sock,
183
socket_get_fd(signd_client->sock),
185
signd_client_socket_handler, signd_client);
186
/* its now the job of the event layer to close the socket */
187
tevent_fd_set_close_fn(signd_client->fde, socket_tevent_fd_close_fn);
188
socket_set_flags(signd_client->sock, SOCKET_FLAG_NOCLOSE);
190
signd_client->status = NT_STATUS_OK;
191
signd_client->reply = data_blob(NULL, 0);
193
signd_client->packet = packet_init(signd_client);
194
if (signd_client->packet == NULL) {
195
talloc_free(signd_client);
198
packet_set_private(signd_client->packet, signd_client);
199
packet_set_socket(signd_client->packet, signd_client->sock);
200
packet_set_callback(signd_client->packet, signd_client_full_packet);
201
packet_set_full_request(signd_client->packet, packet_full_request_u32);
202
packet_set_error_handler(signd_client->packet, signd_client_error_handler);
203
packet_set_event_context(signd_client->packet, tctx->ev);
204
packet_set_fde(signd_client->packet, signd_client->fde);
206
signd_client->request = data_blob_talloc(signd_client, NULL, sign_req_blob.length + 4);
207
RSIVAL(signd_client->request.data, 0, sign_req_blob.length);
208
memcpy(signd_client->request.data+4, sign_req_blob.data, sign_req_blob.length);
209
packet_send(signd_client->packet, signd_client->request);
211
while ((NT_STATUS_IS_OK(signd_client->status)) && !signd_client->reply.length) {
212
if (tevent_loop_once(tctx->ev) != 0) {
213
talloc_free(signd_client);
218
torture_assert_ntstatus_ok(tctx, signd_client->status, "Error reading signd_client reply packet");
220
ndr_err = ndr_pull_struct_blob_all(&signd_client->reply, mem_ctx,
221
lp_iconv_convenience(tctx->lp_ctx),
138
ndr_err = ndr_push_struct_blob(&sign_req_blob,
141
(ndr_push_flags_fn_t)ndr_push_sign_request);
143
NDR_ERR_CODE_IS_SUCCESS(ndr_err),
144
"Failed to push sign_req");
146
signd_client = talloc(mem_ctx, struct signd_client_state);
148
/* Create socket addresses */
149
torture_comment(tctx, "Creating the socket addresses\n");
150
rc = tsocket_address_unix_from_path(signd_client, "",
151
&signd_client->local_address);
152
torture_assert(tctx, rc == 0,
153
"Failed to create local address from unix path.");
155
unix_address = talloc_asprintf(signd_client,
157
lpcfg_ntp_signd_socket_directory(tctx->lp_ctx));
158
rc = tsocket_address_unix_from_path(mem_ctx,
160
&signd_client->remote_address);
161
torture_assert(tctx, rc == 0,
162
"Failed to create remote address from unix path.");
164
/* Connect to the unix socket */
165
torture_comment(tctx, "Connecting to the unix socket\n");
166
req = tstream_unix_connect_send(signd_client,
168
signd_client->local_address,
169
signd_client->remote_address);
170
torture_assert(tctx, req != NULL,
171
"Failed to create a tstream unix connect request.");
173
ok = tevent_req_poll(req, tctx->ev);
174
torture_assert(tctx, ok == true,
175
"Failed to poll for tstream_unix_connect_send.");
177
rc = tstream_unix_connect_recv(req,
180
&signd_client->tstream);
182
torture_assert(tctx, rc == 0, "Failed to connect to signd!");
184
/* Allocate the send queue */
185
signd_client->send_queue = tevent_queue_create(signd_client,
186
"signd_client_queue");
187
torture_assert(tctx, signd_client->send_queue != NULL,
188
"Failed to create send queue!");
191
* Create the request buffer.
192
* First add the length of the request buffer
194
RSIVAL(signd_client->request_hdr, 0, sign_req_blob.length);
195
signd_client->request_iov[0].iov_base = (char *) signd_client->request_hdr;
196
signd_client->request_iov[0].iov_len = 4;
198
signd_client->request_iov[1].iov_base = (char *) sign_req_blob.data;
199
signd_client->request_iov[1].iov_len = sign_req_blob.length;
201
/* Fire the request buffer */
202
torture_comment(tctx, "Sending the request\n");
203
req = tstream_writev_queue_send(signd_client,
205
signd_client->tstream,
206
signd_client->send_queue,
207
signd_client->request_iov, 2);
208
torture_assert(tctx, req != NULL,
209
"Failed to send the signd request.");
211
ok = tevent_req_poll(req, tctx->ev);
212
torture_assert(tctx, ok == true,
213
"Failed to poll for tstream_writev_queue_send.");
215
rc = tstream_writev_queue_recv(req, &sys_errno);
217
torture_assert(tctx, rc > 0, "Failed to send data");
219
/* Wait for a reply */
220
torture_comment(tctx, "Waiting for the reply\n");
221
req = tstream_read_pdu_blob_send(signd_client,
223
signd_client->tstream,
224
4, /*initial_read_size */
225
packet_full_request_u32,
227
torture_assert(tctx, req != NULL,
228
"Failed to setup a read for pdu_blob.");
230
ok = tevent_req_poll(req, tctx->ev);
231
torture_assert(tctx, ok == true,
232
"Failed to poll for tstream_read_pdu_blob_send.");
234
signd_client->status = tstream_read_pdu_blob_recv(req,
236
&signd_client->reply);
237
torture_assert_ntstatus_ok(tctx, signd_client->status,
238
"Error reading signd_client reply packet");
240
/* Skip length header */
241
signd_client->reply.data += 4;
242
signd_client->reply.length -= 4;
244
/* Check if the reply buffer is valid */
245
torture_comment(tctx, "Validating the reply buffer\n");
246
ndr_err = ndr_pull_struct_blob_all(&signd_client->reply,
223
249
(ndr_pull_flags_fn_t)ndr_pull_signed_reply);
224
torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), ndr_map_error2string(ndr_err));
250
torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err),
251
ndr_map_error2string(ndr_err));
226
torture_assert_u64_equal(tctx, signed_reply.version,
227
NTP_SIGND_PROTOCOL_VERSION_0, "Invalid Version");
228
torture_assert_u64_equal(tctx, signed_reply.packet_id,
253
torture_assert_u64_equal(tctx, signed_reply.version,
254
NTP_SIGND_PROTOCOL_VERSION_0,
256
torture_assert_u64_equal(tctx, signed_reply.packet_id,
229
257
sign_req.packet_id, "Invalid Packet ID");
230
torture_assert_u64_equal(tctx, signed_reply.op,
231
SIGNING_SUCCESS, "Should have replied with signing success");
232
torture_assert_u64_equal(tctx, signed_reply.signed_packet.length,
233
sign_req.packet_to_sign.length + 20, "Invalid reply length from signd");
234
torture_assert_u64_equal(tctx, rid,
235
IVAL(signed_reply.signed_packet.data, sign_req.packet_to_sign.length),
258
torture_assert_u64_equal(tctx, signed_reply.op,
260
"Should have replied with signing success");
261
torture_assert_u64_equal(tctx, signed_reply.signed_packet.length,
262
sign_req.packet_to_sign.length + 20,
263
"Invalid reply length from signd");
264
torture_assert_u64_equal(tctx, rid,
265
IVAL(signed_reply.signed_packet.data,
266
sign_req.packet_to_sign.length),
236
267
"Incorrect RID in reply");
238
269
/* Check computed signature */
241
271
MD5Update(&ctx, pwhash->hash, sizeof(pwhash->hash));
242
MD5Update(&ctx, sign_req.packet_to_sign.data, sign_req.packet_to_sign.length);
272
MD5Update(&ctx, sign_req.packet_to_sign.data,
273
sign_req.packet_to_sign.length);
243
274
MD5Final(sig, &ctx);
245
torture_assert_mem_equal(tctx, &signed_reply.signed_packet.data[sign_req.packet_to_sign.length + 4],
276
torture_assert_mem_equal(tctx,
277
&signed_reply.signed_packet.data[sign_req.packet_to_sign.length + 4],
246
278
sig, 16, "Signature on reply was incorrect!");
248
280
talloc_free(mem_ctx);
253
285
NTSTATUS torture_ntp_init(void)
255
struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "NTP");
287
struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "ntp");
256
288
struct torture_rpc_tcase *tcase;
258
tcase = torture_suite_add_machine_workstation_rpc_iface_tcase(suite, "SIGND",
259
&ndr_table_netlogon, TEST_MACHINE_NAME);
290
tcase = torture_suite_add_machine_workstation_rpc_iface_tcase(suite,
291
"signd", &ndr_table_netlogon, TEST_MACHINE_NAME);
261
293
torture_rpc_tcase_add_test_creds(tcase, "ntp_signd", test_ntp_signd);