e82276a08627c24fd8929c4532e4949d3df21332
[bbaumbach/samba-autobuild/.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/torture.h"
24 #include "torture/smbtorture.h"
25 #include <tevent.h>
26 #include "lib/socket/socket.h"
27 #include "lib/stream/packet.h"
28 #include "auth/credentials/credentials.h"
29 #include "torture/rpc/rpc.h"
30 #include "torture/rpc/netlogon.h"
31 #include "../lib/crypto/crypto.h"
32 #include "libcli/auth/libcli_auth.h"
33 #include "librpc/gen_ndr/ndr_netlogon_c.h"
34 #include "librpc/gen_ndr/ndr_netlogon.h"
35 #include "librpc/gen_ndr/ndr_ntp_signd.h"
36 #include "param/param.h"
37
38 #define TEST_MACHINE_NAME "ntpsigndtest"
39
40 struct signd_client_socket {
41         struct socket_context *sock;
42         
43         /* the fd event */
44         struct tevent_fd *fde;
45         
46         NTSTATUS status;
47         DATA_BLOB request, reply;
48         
49         struct packet_context *packet;
50                 
51         size_t partial_read;
52 };
53
54 static NTSTATUS signd_client_full_packet(void *private_data, DATA_BLOB data)
55 {
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;
61         return NT_STATUS_OK;
62 }
63
64 static void signd_client_error_handler(void *private_data, NTSTATUS status)
65 {
66         struct signd_client_socket *signd_client = talloc_get_type(private_data, struct signd_client_socket);
67         signd_client->status = status;
68 }
69
70 /*
71   handle fd events on a signd_client_socket
72 */
73 static void signd_client_socket_handler(struct tevent_context *ev, struct tevent_fd *fde,
74                                  uint16_t flags, void *private_data)
75 {
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);
79                 return;
80         }
81         if (flags & TEVENT_FD_WRITE) {
82                 packet_queue_run(signd_client->packet);
83                 return;
84         }
85         /* not reached */
86         return;
87 }
88
89 /* A torture test to show that the unix domain socket protocol is
90  * operating correctly, and the signatures are as expected */
91
92 static bool test_ntp_signd(struct torture_context *tctx, 
93                            struct dcerpc_pipe *p,
94                            struct cli_credentials *credentials)
95 {
96         struct netlogon_creds_CredentialState *creds;
97         TALLOC_CTX *mem_ctx = talloc_new(tctx);
98
99         NTSTATUS status;
100         struct netr_ServerReqChallenge r;
101         struct netr_ServerAuthenticate3 a;
102         struct netr_Credential credentials1, credentials2, credentials3;
103         uint32_t rid;
104         const char *machine_name;
105         const struct samr_Password *pwhash = cli_credentials_get_nt_hash(credentials, mem_ctx);
106         uint32_t negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
107
108         struct sign_request sign_req;
109         struct signed_reply signed_reply;
110         DATA_BLOB sign_req_blob;
111
112         struct signd_client_socket *signd_client;
113         char *signd_socket_address;
114
115         struct MD5Context ctx;
116         uint8_t sig[16];
117         enum ndr_err_code ndr_err;
118
119         machine_name = cli_credentials_get_workstation(credentials);
120
121         torture_comment(tctx, "Testing ServerReqChallenge\n");
122
123         r.in.server_name = NULL;
124         r.in.computer_name = machine_name;
125         r.in.credentials = &credentials1;
126         r.out.return_credentials = &credentials2;
127
128         generate_random_buffer(credentials1.data, sizeof(credentials1.data));
129
130         status = dcerpc_netr_ServerReqChallenge(p, tctx, &r);
131         torture_assert_ntstatus_ok(tctx, status, "ServerReqChallenge");
132
133         a.in.server_name = NULL;
134         a.in.account_name = talloc_asprintf(tctx, "%s$", machine_name);
135         a.in.secure_channel_type = SEC_CHAN_WKSTA;
136         a.in.computer_name = machine_name;
137         a.in.negotiate_flags = &negotiate_flags;
138         a.in.credentials = &credentials3;
139         a.out.return_credentials = &credentials3;
140         a.out.negotiate_flags = &negotiate_flags;
141         a.out.rid = &rid;
142
143         creds = netlogon_creds_client_init(tctx, a.in.account_name,
144                                            a.in.computer_name,
145                                            &credentials1, &credentials2, 
146                                            pwhash, &credentials3,
147                                            negotiate_flags);
148         
149         torture_assert(tctx, creds != NULL, "memory allocation");
150
151         torture_comment(tctx, "Testing ServerAuthenticate3\n");
152
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");
156
157         sign_req.version = 1;
158         sign_req.op = SIGN_TO_CLIENT;
159         sign_req.packet_id = 1;
160         sign_req.key_id = rid;
161         sign_req.packet_to_sign = data_blob_string_const("I am a tea pot");
162         
163         ndr_err = ndr_push_struct_blob(&sign_req_blob, mem_ctx, NULL, &sign_req, (ndr_push_flags_fn_t)ndr_push_sign_request);
164         torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), "Failed to push sign_req");
165         
166         signd_client = talloc(mem_ctx, struct signd_client_socket);
167
168         status = socket_create("unix", SOCKET_TYPE_STREAM, &signd_client->sock, 0);
169         
170         signd_socket_address = talloc_asprintf(signd_client, "%s/socket", 
171                                                lp_ntp_signd_socket_directory(tctx->lp_ctx));
172
173         status = socket_connect_ev(signd_client->sock, NULL, 
174                                    socket_address_from_strings(signd_client, 
175                                                                "unix", signd_socket_address, 0), 0, tctx->ev);
176         torture_assert_ntstatus_ok(tctx, status, "Failed to connect to signd!");
177         
178         /* Setup the FDE, start listening for read events
179          * from the start (otherwise we may miss a socket
180          * drop) and mark as AUTOCLOSE along with the fde */
181         
182         /* Ths is equivilant to EVENT_FD_READABLE(signd_client->fde) */
183         signd_client->fde = tevent_add_fd(tctx->ev, signd_client->sock,
184                             socket_get_fd(signd_client->sock),
185                             TEVENT_FD_READ,
186                             signd_client_socket_handler, signd_client);
187         /* its now the job of the event layer to close the socket */
188         tevent_fd_set_close_fn(signd_client->fde, socket_tevent_fd_close_fn);
189         socket_set_flags(signd_client->sock, SOCKET_FLAG_NOCLOSE);
190         
191         signd_client->status = NT_STATUS_OK;
192         signd_client->reply = data_blob(NULL, 0);
193
194         signd_client->packet = packet_init(signd_client);
195         if (signd_client->packet == NULL) {
196                 talloc_free(signd_client);
197                 return ENOMEM;
198         }
199         packet_set_private(signd_client->packet, signd_client);
200         packet_set_socket(signd_client->packet, signd_client->sock);
201         packet_set_callback(signd_client->packet, signd_client_full_packet);
202         packet_set_full_request(signd_client->packet, packet_full_request_u32);
203         packet_set_error_handler(signd_client->packet, signd_client_error_handler);
204         packet_set_event_context(signd_client->packet, tctx->ev);
205         packet_set_fde(signd_client->packet, signd_client->fde);
206         
207         signd_client->request = data_blob_talloc(signd_client, NULL, sign_req_blob.length + 4);
208         RSIVAL(signd_client->request.data, 0, sign_req_blob.length);
209         memcpy(signd_client->request.data+4, sign_req_blob.data, sign_req_blob.length);
210         packet_send(signd_client->packet, signd_client->request);
211
212         while ((NT_STATUS_IS_OK(signd_client->status)) && !signd_client->reply.length) {
213                 if (tevent_loop_once(tctx->ev) != 0) {
214                         talloc_free(signd_client);
215                         return EINVAL;
216                 }
217         }
218
219         torture_assert_ntstatus_ok(tctx, signd_client->status, "Error reading signd_client reply packet");
220
221         ndr_err = ndr_pull_struct_blob_all(&signd_client->reply, mem_ctx, 
222                                            lp_iconv_convenience(tctx->lp_ctx),
223                                            &signed_reply,
224                                            (ndr_pull_flags_fn_t)ndr_pull_signed_reply);
225         torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), ndr_map_error2string(ndr_err));
226
227         torture_assert_u64_equal(tctx, signed_reply.version, 
228                                  sign_req.version, "Invalid Version");
229         torture_assert_u64_equal(tctx, signed_reply.packet_id, 
230                                  sign_req.packet_id, "Invalid Packet ID");
231         torture_assert_u64_equal(tctx, signed_reply.op, 
232                                  SIGNING_SUCCESS, "Should have replied with signing success");
233         torture_assert_u64_equal(tctx, signed_reply.signed_packet.length, 
234                                  sign_req.packet_to_sign.length + 20, "Invalid reply length from signd");
235         torture_assert_u64_equal(tctx, rid, 
236                                  IVAL(signed_reply.signed_packet.data, sign_req.packet_to_sign.length), 
237                                  "Incorrect RID in reply");
238
239         /* Check computed signature */
240
241         MD5Init(&ctx);
242         MD5Update(&ctx, pwhash->hash, sizeof(pwhash->hash));
243         MD5Update(&ctx, sign_req.packet_to_sign.data, sign_req.packet_to_sign.length);
244         MD5Final(sig, &ctx);
245
246         torture_assert_mem_equal(tctx, &signed_reply.signed_packet.data[sign_req.packet_to_sign.length + 4],
247                                  sig, 16, "Signature on reply was incorrect!");
248         
249         talloc_free(mem_ctx);
250                 
251         return true;
252 }
253
254 NTSTATUS torture_ntp_init(void)
255 {
256         struct torture_suite *suite = torture_suite_create(talloc_autofree_context(), "NTP");
257         struct torture_rpc_tcase *tcase;
258
259         tcase = torture_suite_add_machine_workstation_rpc_iface_tcase(suite, "SIGND",
260                                                                       &ndr_table_netlogon, TEST_MACHINE_NAME);
261
262         torture_rpc_tcase_add_test_creds(tcase, "ntp_signd", test_ntp_signd);
263
264         suite->description = talloc_strdup(suite, "NTP tests");
265
266         torture_register_suite(suite);
267
268         return NT_STATUS_OK;
269 }
270