CVE-2022-38023 s4:torture: use NETLOGON_NEG_SUPPORTS_AES by default
[samba.git] / source4 / torture / ntp / ntp_signd.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Test NTP authentication support
5
6    Copyright (C) Andrew Bartlet <abartlet@samba.org> 2008
7    
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.
12    
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.
17    
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/>.
20 */
21
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"
35
36 #include <gnutls/gnutls.h>
37 #include <gnutls/crypto.h>
38
39 #define TEST_MACHINE_NAME "ntpsigndtest"
40
41 struct signd_client_state {
42         struct tsocket_address *local_address;
43         struct tsocket_address *remote_address;
44
45         struct tstream_context *tstream;
46         struct tevent_queue *send_queue;
47
48         uint8_t request_hdr[4];
49         struct iovec request_iov[2];
50
51         DATA_BLOB reply;
52
53         NTSTATUS status;
54 };
55
56 /*
57  * A torture test to show that the unix domain socket protocol is
58  * operating correctly, and the signatures are as expected
59  */
60 static bool test_ntp_signd(struct torture_context *tctx,
61                            struct dcerpc_pipe *p,
62                            struct cli_credentials *credentials)
63 {
64         struct netlogon_creds_CredentialState *creds;
65         TALLOC_CTX *mem_ctx = talloc_new(tctx);
66
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;
74
75         struct sign_request sign_req;
76         struct signed_reply signed_reply;
77         DATA_BLOB sign_req_blob;
78
79         struct signd_client_state *signd_client;
80         struct tevent_req *req;
81         char *unix_address;
82         int sys_errno;
83
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;
89
90         machine_name = cli_credentials_get_workstation(credentials);
91
92         torture_comment(tctx, "Testing ServerReqChallenge\n");
93
94         r.in.server_name = NULL;
95         r.in.computer_name = machine_name;
96         r.in.credentials = &credentials1;
97         r.out.return_credentials = &credentials2;
98
99         generate_random_buffer(credentials1.data, sizeof(credentials1.data));
100
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");
106
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;
116
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);
123         
124         torture_assert(tctx, creds != NULL, "memory allocation");
125
126         torture_comment(tctx, "Testing ServerAuthenticate3\n");
127
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");
136
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");
141         
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");
149
150         signd_client = talloc(mem_ctx, struct signd_client_state);
151
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.");
158
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.");
167
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.");
176
177         ok = tevent_req_poll(req, tctx->ev);
178         torture_assert(tctx, ok == true,
179                        "Failed to poll for tstream_unix_connect_send.");
180
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!");
187
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!");
193
194         /*
195          * Create the request buffer.
196          * First add the length of the request buffer
197          */
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;
201
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;
204
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.");
214
215         ok = tevent_req_poll(req, tctx->ev);
216         torture_assert(tctx, ok == true,
217                        "Failed to poll for tstream_writev_queue_send.");
218
219         rc = tstream_writev_queue_recv(req, &sys_errno);
220         TALLOC_FREE(req);
221         torture_assert(tctx, rc > 0, "Failed to send data");
222
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                                          packet_full_request_u32,
230                                          NULL);
231         torture_assert(tctx, req != NULL,
232                        "Failed to setup a read for pdu_blob.");
233
234         ok = tevent_req_poll(req, tctx->ev);
235         torture_assert(tctx, ok == true,
236                        "Failed to poll for tstream_read_pdu_blob_send.");
237
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");
243
244         /* Skip length header */
245         signd_client->reply.data += 4;
246         signd_client->reply.length -= 4;
247
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));
256
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");
272
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);
280
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!");
284
285         talloc_free(mem_ctx);
286
287         return true;
288 }
289
290 NTSTATUS torture_ntp_init(TALLOC_CTX *ctx)
291 {
292         struct torture_suite *suite = torture_suite_create(ctx, "ntp");
293         struct torture_rpc_tcase *tcase;
294
295         tcase = torture_suite_add_machine_workstation_rpc_iface_tcase(suite,
296                                   "signd", &ndr_table_netlogon, TEST_MACHINE_NAME);
297
298         torture_rpc_tcase_add_test_creds(tcase, "ntp_signd", test_ntp_signd);
299
300         suite->description = talloc_strdup(suite, "NTP tests");
301
302         torture_register_suite(ctx, suite);
303
304         return NT_STATUS_OK;
305 }
306