docs: Document parametric form of hide and veto files
[Samba.git] / source4 / torture / ntp / ntp_signd.c
blobfd7da67c5518b26af3859ad48021ebe10496ce0d
1 /*
2 Unix SMB/CIFS implementation.
4 Test NTP authentication support
6 Copyright (C) Andrew Bartlet <abartlet@samba.org> 2008
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "torture/smbtorture.h"
24 #include <tevent.h>
25 #include "lib/stream/packet.h"
26 #include "lib/tsocket/tsocket.h"
27 #include "libcli/util/tstream.h"
28 #include "torture/rpc/torture_rpc.h"
29 #include "libcli/auth/libcli_auth.h"
30 #include "librpc/gen_ndr/ndr_netlogon_c.h"
31 #include "librpc/gen_ndr/ndr_ntp_signd.h"
32 #include "param/param.h"
33 #include "system/network.h"
34 #include "torture/ntp/proto.h"
36 #include <gnutls/gnutls.h>
37 #include <gnutls/crypto.h>
39 #define TEST_MACHINE_NAME "ntpsigndtest"
41 struct signd_client_state {
42 struct tsocket_address *local_address;
43 struct tsocket_address *remote_address;
45 struct tstream_context *tstream;
46 struct tevent_queue *send_queue;
48 uint8_t request_hdr[4];
49 struct iovec request_iov[2];
51 DATA_BLOB reply;
53 NTSTATUS status;
57 * A torture test to show that the unix domain socket protocol is
58 * operating correctly, and the signatures are as expected
60 static bool test_ntp_signd(struct torture_context *tctx,
61 struct dcerpc_pipe *p,
62 struct cli_credentials *credentials)
64 struct netlogon_creds_CredentialState *creds;
65 TALLOC_CTX *mem_ctx = talloc_new(tctx);
67 struct netr_ServerReqChallenge r;
68 struct netr_ServerAuthenticate3 a;
69 struct netr_Credential credentials1, credentials2, credentials3;
70 uint32_t rid;
71 const char *machine_name;
72 const struct samr_Password *pwhash = cli_credentials_get_nt_hash(credentials, mem_ctx);
73 uint32_t negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS | NETLOGON_NEG_SUPPORTS_AES;
75 struct sign_request sign_req;
76 struct signed_reply signed_reply;
77 DATA_BLOB sign_req_blob;
79 struct signd_client_state *signd_client;
80 struct tevent_req *req;
81 char *unix_address;
82 int sys_errno;
84 gnutls_hash_hd_t hash_hnd;
85 uint8_t sig[16];
86 enum ndr_err_code ndr_err;
87 bool ok;
88 int rc;
90 machine_name = cli_credentials_get_workstation(credentials);
92 torture_comment(tctx, "Testing ServerReqChallenge\n");
94 r.in.server_name = NULL;
95 r.in.computer_name = machine_name;
96 r.in.credentials = &credentials1;
97 r.out.return_credentials = &credentials2;
99 generate_random_buffer(credentials1.data, sizeof(credentials1.data));
101 torture_assert_ntstatus_ok(tctx,
102 dcerpc_netr_ServerReqChallenge_r(p->binding_handle, tctx, &r),
103 "ServerReqChallenge failed");
104 torture_assert_ntstatus_ok(tctx, r.out.result,
105 "ServerReqChallenge failed");
107 a.in.server_name = NULL;
108 a.in.account_name = talloc_asprintf(tctx, "%s$", machine_name);
109 a.in.secure_channel_type = SEC_CHAN_WKSTA;
110 a.in.computer_name = machine_name;
111 a.in.negotiate_flags = &negotiate_flags;
112 a.in.credentials = &credentials3;
113 a.out.return_credentials = &credentials3;
114 a.out.negotiate_flags = &negotiate_flags;
115 a.out.rid = &rid;
117 creds = netlogon_creds_client_init(tctx, a.in.account_name,
118 a.in.computer_name,
119 a.in.secure_channel_type,
120 &credentials1, &credentials2,
121 pwhash, &credentials3,
122 negotiate_flags);
124 torture_assert(tctx, creds != NULL, "memory allocation");
126 torture_comment(tctx, "Testing ServerAuthenticate3\n");
128 torture_assert_ntstatus_ok(tctx,
129 dcerpc_netr_ServerAuthenticate3_r(p->binding_handle, tctx, &a),
130 "ServerAuthenticate3 failed");
131 torture_assert_ntstatus_ok(tctx, a.out.result,
132 "ServerAuthenticate3 failed");
133 torture_assert(tctx,
134 netlogon_creds_client_check(creds, &credentials3),
135 "Credential chaining failed");
137 sign_req.op = SIGN_TO_CLIENT;
138 sign_req.packet_id = 1;
139 sign_req.key_id = rid;
140 sign_req.packet_to_sign = data_blob_string_const("I am a tea pot");
142 ndr_err = ndr_push_struct_blob(&sign_req_blob,
143 mem_ctx,
144 &sign_req,
145 (ndr_push_flags_fn_t)ndr_push_sign_request);
146 torture_assert(tctx,
147 NDR_ERR_CODE_IS_SUCCESS(ndr_err),
148 "Failed to push sign_req");
150 signd_client = talloc(mem_ctx, struct signd_client_state);
152 /* Create socket addresses */
153 torture_comment(tctx, "Creating the socket addresses\n");
154 rc = tsocket_address_unix_from_path(signd_client, "",
155 &signd_client->local_address);
156 torture_assert(tctx, rc == 0,
157 "Failed to create local address from unix path.");
159 unix_address = talloc_asprintf(signd_client,
160 "%s/socket",
161 lpcfg_ntp_signd_socket_directory(tctx->lp_ctx));
162 rc = tsocket_address_unix_from_path(mem_ctx,
163 unix_address,
164 &signd_client->remote_address);
165 torture_assert(tctx, rc == 0,
166 "Failed to create remote address from unix path.");
168 /* Connect to the unix socket */
169 torture_comment(tctx, "Connecting to the unix socket\n");
170 req = tstream_unix_connect_send(signd_client,
171 tctx->ev,
172 signd_client->local_address,
173 signd_client->remote_address);
174 torture_assert(tctx, req != NULL,
175 "Failed to create a tstream unix connect request.");
177 ok = tevent_req_poll(req, tctx->ev);
178 torture_assert(tctx, ok == true,
179 "Failed to poll for tstream_unix_connect_send.");
181 rc = tstream_unix_connect_recv(req,
182 &sys_errno,
183 signd_client,
184 &signd_client->tstream);
185 TALLOC_FREE(req);
186 torture_assert(tctx, rc == 0, "Failed to connect to signd!");
188 /* Allocate the send queue */
189 signd_client->send_queue = tevent_queue_create(signd_client,
190 "signd_client_queue");
191 torture_assert(tctx, signd_client->send_queue != NULL,
192 "Failed to create send queue!");
195 * Create the request buffer.
196 * First add the length of the request buffer
198 RSIVAL(signd_client->request_hdr, 0, sign_req_blob.length);
199 signd_client->request_iov[0].iov_base = (char *) signd_client->request_hdr;
200 signd_client->request_iov[0].iov_len = 4;
202 signd_client->request_iov[1].iov_base = (char *) sign_req_blob.data;
203 signd_client->request_iov[1].iov_len = sign_req_blob.length;
205 /* Fire the request buffer */
206 torture_comment(tctx, "Sending the request\n");
207 req = tstream_writev_queue_send(signd_client,
208 tctx->ev,
209 signd_client->tstream,
210 signd_client->send_queue,
211 signd_client->request_iov, 2);
212 torture_assert(tctx, req != NULL,
213 "Failed to send the signd request.");
215 ok = tevent_req_poll(req, tctx->ev);
216 torture_assert(tctx, ok == true,
217 "Failed to poll for tstream_writev_queue_send.");
219 rc = tstream_writev_queue_recv(req, &sys_errno);
220 TALLOC_FREE(req);
221 torture_assert(tctx, rc > 0, "Failed to send data");
223 /* Wait for a reply */
224 torture_comment(tctx, "Waiting for the reply\n");
225 req = tstream_read_pdu_blob_send(signd_client,
226 tctx->ev,
227 signd_client->tstream,
228 4, /*initial_read_size */
229 tstream_full_request_u32,
230 NULL);
231 torture_assert(tctx, req != NULL,
232 "Failed to setup a read for pdu_blob.");
234 ok = tevent_req_poll(req, tctx->ev);
235 torture_assert(tctx, ok == true,
236 "Failed to poll for tstream_read_pdu_blob_send.");
238 signd_client->status = tstream_read_pdu_blob_recv(req,
239 signd_client,
240 &signd_client->reply);
241 torture_assert_ntstatus_ok(tctx, signd_client->status,
242 "Error reading signd_client reply packet");
244 /* Skip length header */
245 signd_client->reply.data += 4;
246 signd_client->reply.length -= 4;
248 /* Check if the reply buffer is valid */
249 torture_comment(tctx, "Validating the reply buffer\n");
250 ndr_err = ndr_pull_struct_blob_all(&signd_client->reply,
251 mem_ctx,
252 &signed_reply,
253 (ndr_pull_flags_fn_t)ndr_pull_signed_reply);
254 torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err),
255 ndr_map_error2string(ndr_err));
257 torture_assert_u64_equal(tctx, signed_reply.version,
258 NTP_SIGND_PROTOCOL_VERSION_0,
259 "Invalid Version");
260 torture_assert_u64_equal(tctx, signed_reply.packet_id,
261 sign_req.packet_id, "Invalid Packet ID");
262 torture_assert_u64_equal(tctx, signed_reply.op,
263 SIGNING_SUCCESS,
264 "Should have replied with signing success");
265 torture_assert_u64_equal(tctx, signed_reply.signed_packet.length,
266 sign_req.packet_to_sign.length + 20,
267 "Invalid reply length from signd");
268 torture_assert_u64_equal(tctx, rid,
269 IVAL(signed_reply.signed_packet.data,
270 sign_req.packet_to_sign.length),
271 "Incorrect RID in reply");
273 /* Check computed signature */
274 gnutls_hash_init(&hash_hnd, GNUTLS_DIG_MD5);
275 gnutls_hash(hash_hnd, pwhash->hash, sizeof(pwhash->hash));
276 gnutls_hash(hash_hnd,
277 sign_req.packet_to_sign.data,
278 sign_req.packet_to_sign.length);
279 gnutls_hash_deinit(hash_hnd, sig);
281 torture_assert_mem_equal(tctx,
282 &signed_reply.signed_packet.data[sign_req.packet_to_sign.length + 4],
283 sig, 16, "Signature on reply was incorrect!");
285 talloc_free(mem_ctx);
287 return true;
290 NTSTATUS torture_ntp_init(TALLOC_CTX *ctx)
292 struct torture_suite *suite = torture_suite_create(ctx, "ntp");
293 struct torture_rpc_tcase *tcase;
295 tcase = torture_suite_add_machine_workstation_rpc_iface_tcase(suite,
296 "signd", &ndr_table_netlogon, TEST_MACHINE_NAME);
298 torture_rpc_tcase_add_test_creds(tcase, "ntp_signd", test_ntp_signd);
300 suite->description = talloc_strdup(suite, "NTP tests");
302 torture_register_suite(ctx, suite);
304 return NT_STATUS_OK;