s4-ntp_signd: Migrate to tsocket.
[Samba/nascimento.git] / source4 / ntp_signd / ntp_signd.c
blob025ff2be84f568715d81f76adfba1a9b41f2dc34
1 /*
2 Unix SMB/CIFS implementation.
4 NTP packet signing server
6 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
7 Copyright (C) Andrew Tridgell 2005
8 Copyright (C) Stefan Metzmacher 2005
10 This program is free software; you can redistribute it and/or modify
11 it under the terms of the GNU General Public License as published by
12 the Free Software Foundation; either version 3 of the License, or
13 (at your option) any later version.
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License for more details.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "includes.h"
25 #include "smbd/service_task.h"
26 #include "smbd/service.h"
27 #include "smbd/service_stream.h"
28 #include "smbd/process_model.h"
29 #include "lib/stream/packet.h"
30 #include "lib/tsocket/tsocket.h"
31 #include "libcli/util/tstream.h"
32 #include "librpc/gen_ndr/ndr_ntp_signd.h"
33 #include "param/param.h"
34 #include "dsdb/samdb/samdb.h"
35 #include "auth/auth.h"
36 #include "libcli/security/security.h"
37 #include "lib/ldb/include/ldb.h"
38 #include "lib/ldb/include/ldb_errors.h"
39 #include "../lib/crypto/md5.h"
40 #include "system/network.h"
41 #include "system/passwd.h"
44 top level context structure for the ntp_signd server
46 struct ntp_signd_server {
47 struct task_server *task;
48 struct ldb_context *samdb;
52 state of an open connection
54 struct ntp_signd_connection {
55 /* stream connection we belong to */
56 struct stream_connection *conn;
58 /* the ntp_signd_server the connection belongs to */
59 struct ntp_signd_server *ntp_signd;
61 struct tstream_context *tstream;
63 struct tevent_queue *send_queue;
66 static void ntp_signd_terminate_connection(struct ntp_signd_connection *ntp_signd_conn, const char *reason)
68 stream_terminate_connection(ntp_signd_conn->conn, reason);
71 static NTSTATUS signing_failure(struct ntp_signd_connection *ntp_signdconn,
72 TALLOC_CTX *mem_ctx,
73 DATA_BLOB *output,
74 uint32_t packet_id)
76 struct signed_reply signed_reply;
77 enum ndr_err_code ndr_err;
79 signed_reply.op = SIGNING_FAILURE;
80 signed_reply.packet_id = packet_id;
81 signed_reply.signed_packet = data_blob(NULL, 0);
83 ndr_err = ndr_push_struct_blob(output, mem_ctx,
84 lp_iconv_convenience(ntp_signdconn->ntp_signd->task->lp_ctx),
85 &signed_reply,
86 (ndr_push_flags_fn_t)ndr_push_signed_reply);
88 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
89 DEBUG(1,("failed to push ntp error reply\n"));
90 return ndr_map_error2ntstatus(ndr_err);
93 return NT_STATUS_OK;
97 receive a full packet on a NTP_SIGND connection
99 static NTSTATUS ntp_signd_process(struct ntp_signd_connection *ntp_signd_conn,
100 TALLOC_CTX *mem_ctx,
101 DATA_BLOB *input,
102 DATA_BLOB *output)
104 const struct dom_sid *domain_sid;
105 struct dom_sid *sid;
106 struct sign_request sign_request;
107 struct signed_reply signed_reply;
108 enum ndr_err_code ndr_err;
109 struct ldb_result *res;
110 const char *attrs[] = { "unicodePwd", "userAccountControl", "cn", NULL };
111 struct MD5Context ctx;
112 struct samr_Password *nt_hash;
113 uint32_t user_account_control;
114 int ret;
116 ndr_err = ndr_pull_struct_blob_all(input, mem_ctx,
117 lp_iconv_convenience(ntp_signd_conn->ntp_signd->task->lp_ctx),
118 &sign_request,
119 (ndr_pull_flags_fn_t)ndr_pull_sign_request);
121 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
122 DEBUG(1,("failed to parse ntp signing request\n"));
123 dump_data(1, input->data, input->length);
124 return ndr_map_error2ntstatus(ndr_err);
127 /* We need to implement 'check signature' and 'request server
128 * to sign' operations at some point */
129 if (sign_request.op != SIGN_TO_CLIENT) {
130 return signing_failure(ntp_signd_conn,
131 mem_ctx,
132 output,
133 sign_request.packet_id);
136 /* We need to implement 'check signature' and 'request server
137 * to sign' operations at some point */
138 if (sign_request.version != NTP_SIGND_PROTOCOL_VERSION_0) {
139 return signing_failure(ntp_signd_conn,
140 mem_ctx,
141 output,
142 sign_request.packet_id);
145 domain_sid = samdb_domain_sid(ntp_signd_conn->ntp_signd->samdb);
146 if (domain_sid == NULL) {
147 return signing_failure(ntp_signd_conn,
148 mem_ctx,
149 output,
150 sign_request.packet_id);
153 /* The top bit is a 'key selector' */
154 sid = dom_sid_add_rid(mem_ctx, domain_sid,
155 sign_request.key_id & 0x7FFFFFFF);
156 if (sid == NULL) {
157 talloc_free(mem_ctx);
158 return signing_failure(ntp_signd_conn,
159 mem_ctx,
160 output,
161 sign_request.packet_id);
164 ret = ldb_search(ntp_signd_conn->ntp_signd->samdb, mem_ctx,
165 &res,
166 samdb_base_dn(ntp_signd_conn->ntp_signd->samdb),
167 LDB_SCOPE_SUBTREE,
168 attrs,
169 "(&(objectSid=%s)(objectClass=user))",
170 dom_sid_string(mem_ctx, sid));
171 if (ret != LDB_SUCCESS) {
172 DEBUG(2, ("Failed to search for SID %s in SAM for NTP signing: "
173 "%s\n",
174 dom_sid_string(mem_ctx, sid),
175 ldb_errstring(ntp_signd_conn->ntp_signd->samdb)));
176 return signing_failure(ntp_signd_conn,
177 mem_ctx,
178 output,
179 sign_request.packet_id);
182 if (res->count == 0) {
183 DEBUG(5, ("Failed to find SID %s in SAM for NTP signing\n",
184 dom_sid_string(mem_ctx, sid)));
185 } else if (res->count != 1) {
186 DEBUG(1, ("Found SID %s %u times in SAM for NTP signing\n",
187 dom_sid_string(mem_ctx, sid), res->count));
188 return signing_failure(ntp_signd_conn,
189 mem_ctx,
190 output,
191 sign_request.packet_id);
194 user_account_control = ldb_msg_find_attr_as_uint(res->msgs[0],
195 "userAccountControl",
198 if (user_account_control & UF_ACCOUNTDISABLE) {
199 DEBUG(1, ("Account %s for SID [%s] is disabled\n",
200 ldb_dn_get_linearized(res->msgs[0]->dn),
201 dom_sid_string(mem_ctx, sid)));
202 return NT_STATUS_ACCESS_DENIED;
205 if (!(user_account_control & (UF_INTERDOMAIN_TRUST_ACCOUNT|UF_SERVER_TRUST_ACCOUNT|UF_WORKSTATION_TRUST_ACCOUNT))) {
206 DEBUG(1, ("Account %s for SID [%s] is not a trust account\n",
207 ldb_dn_get_linearized(res->msgs[0]->dn),
208 dom_sid_string(mem_ctx, sid)));
209 return NT_STATUS_ACCESS_DENIED;
212 nt_hash = samdb_result_hash(mem_ctx, res->msgs[0], "unicodePwd");
213 if (!nt_hash) {
214 DEBUG(1, ("No unicodePwd found on record of SID %s "
215 "for NTP signing\n", dom_sid_string(mem_ctx, sid)));
216 return signing_failure(ntp_signd_conn,
217 mem_ctx,
218 output,
219 sign_request.packet_id);
222 /* Generate the reply packet */
223 signed_reply.packet_id = sign_request.packet_id;
224 signed_reply.op = SIGNING_SUCCESS;
225 signed_reply.signed_packet = data_blob_talloc(mem_ctx,
226 NULL,
227 sign_request.packet_to_sign.length + 20);
229 if (!signed_reply.signed_packet.data) {
230 return signing_failure(ntp_signd_conn,
231 mem_ctx,
232 output,
233 sign_request.packet_id);
236 memcpy(signed_reply.signed_packet.data, sign_request.packet_to_sign.data, sign_request.packet_to_sign.length);
237 SIVAL(signed_reply.signed_packet.data, sign_request.packet_to_sign.length, sign_request.key_id);
239 /* Sign the NTP response with the unicodePwd */
240 MD5Init(&ctx);
241 MD5Update(&ctx, nt_hash->hash, sizeof(nt_hash->hash));
242 MD5Update(&ctx, sign_request.packet_to_sign.data, sign_request.packet_to_sign.length);
243 MD5Final(signed_reply.signed_packet.data + sign_request.packet_to_sign.length + 4, &ctx);
246 /* Place it into the packet for the wire */
247 ndr_err = ndr_push_struct_blob(output, mem_ctx,
248 lp_iconv_convenience(ntp_signd_conn->ntp_signd->task->lp_ctx),
249 &signed_reply,
250 (ndr_push_flags_fn_t)ndr_push_signed_reply);
252 if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
253 DEBUG(1,("failed to push ntp error reply\n"));
254 return ndr_map_error2ntstatus(ndr_err);
257 return NT_STATUS_OK;
261 called on a tcp recv
263 static void ntp_signd_recv(struct stream_connection *conn, uint16_t flags)
265 struct ntp_signd_connection *ntp_signd_conn = talloc_get_type(conn->private_data,
266 struct ntp_signd_connection);
267 ntp_signd_terminate_connection(ntp_signd_conn,
268 "ntp_signd_recv: called");
272 called when we can write to a connection
274 static void ntp_signd_send(struct stream_connection *conn, uint16_t flags)
276 struct ntp_signd_connection *ntp_signd_conn = talloc_get_type(conn->private_data,
277 struct ntp_signd_connection);
278 /* this should never be triggered! */
279 ntp_signd_terminate_connection(ntp_signd_conn,
280 "ntp_signd_send: called");
283 struct ntp_signd_call {
284 struct ntp_signd_connection *ntp_signd_conn;
285 DATA_BLOB in;
286 DATA_BLOB out;
287 uint8_t out_hdr[4];
288 struct iovec out_iov[2];
291 static void ntp_signd_call_writev_done(struct tevent_req *subreq);
293 static void ntp_signd_call_loop(struct tevent_req *subreq)
295 struct ntp_signd_connection *ntp_signd_conn = tevent_req_callback_data(subreq,
296 struct ntp_signd_connection);
297 struct ntp_signd_call *call;
298 NTSTATUS status;
300 call = talloc(ntp_signd_conn, struct ntp_signd_call);
301 if (call == NULL) {
302 ntp_signd_terminate_connection(ntp_signd_conn,
303 "ntp_signd_call_loop: "
304 "no memory for ntp_signd_call");
305 return;
307 call->ntp_signd_conn = ntp_signd_conn;
309 status = tstream_read_pdu_blob_recv(subreq,
310 call,
311 &call->in);
312 TALLOC_FREE(subreq);
313 if (!NT_STATUS_IS_OK(status)) {
314 const char *reason;
316 reason = talloc_asprintf(call, "ntp_signd_call_loop: "
317 "tstream_read_pdu_blob_recv() - %s",
318 nt_errstr(status));
319 if (reason == NULL) {
320 reason = nt_errstr(status);
323 ntp_signd_terminate_connection(ntp_signd_conn, reason);
324 return;
327 DEBUG(10,("Received NTP TCP packet of length %lu from %s\n",
328 (long) call->in.length,
329 tsocket_address_string(ntp_signd_conn->conn->remote_address, call)));
331 /* skip length header */
332 call->in.data +=4;
333 call->in.length -= 4;
335 status = ntp_signd_process(ntp_signd_conn,
336 call,
337 &call->in,
338 &call->out);
339 if (! NT_STATUS_IS_OK(status)) {
340 const char *reason;
342 reason = talloc_asprintf(call, "ntp_signd_process failed: %s",
343 nt_errstr(status));
344 if (reason == NULL) {
345 reason = nt_errstr(status);
348 ntp_signd_terminate_connection(ntp_signd_conn, reason);
349 return;
352 /* First add the length of the out buffer */
353 RSIVAL(call->out_hdr, 0, call->out.length);
354 call->out_iov[0].iov_base = call->out_hdr;
355 call->out_iov[0].iov_len = 4;
357 call->out_iov[1].iov_base = call->out.data;
358 call->out_iov[1].iov_len = call->out.length;
360 subreq = tstream_writev_queue_send(call,
361 ntp_signd_conn->conn->event.ctx,
362 ntp_signd_conn->tstream,
363 ntp_signd_conn->send_queue,
364 call->out_iov, 2);
365 if (subreq == NULL) {
366 ntp_signd_terminate_connection(ntp_signd_conn, "ntp_signd_call_loop: "
367 "no memory for tstream_writev_queue_send");
368 return;
371 tevent_req_set_callback(subreq, ntp_signd_call_writev_done, call);
374 * The NTP tcp pdu's has the length as 4 byte (initial_read_size),
375 * packet_full_request_u32 provides the pdu length then.
377 subreq = tstream_read_pdu_blob_send(ntp_signd_conn,
378 ntp_signd_conn->conn->event.ctx,
379 ntp_signd_conn->tstream,
380 4, /* initial_read_size */
381 packet_full_request_u32,
382 ntp_signd_conn);
383 if (subreq == NULL) {
384 ntp_signd_terminate_connection(ntp_signd_conn, "ntp_signd_call_loop: "
385 "no memory for tstream_read_pdu_blob_send");
386 return;
388 tevent_req_set_callback(subreq, ntp_signd_call_loop, ntp_signd_conn);
391 static void ntp_signd_call_writev_done(struct tevent_req *subreq)
393 struct ntp_signd_call *call = tevent_req_callback_data(subreq,
394 struct ntp_signd_call);
395 int sys_errno;
396 int rc;
398 rc = tstream_writev_queue_recv(subreq, &sys_errno);
399 TALLOC_FREE(subreq);
400 if (rc == -1) {
401 const char *reason;
403 reason = talloc_asprintf(call, "ntp_signd_call_writev_done: "
404 "tstream_writev_queue_recv() - %d:%s",
405 sys_errno, strerror(sys_errno));
406 if (!reason) {
407 reason = "ntp_signd_call_writev_done: "
408 "tstream_writev_queue_recv() failed";
411 ntp_signd_terminate_connection(call->ntp_signd_conn, reason);
412 return;
415 /* We don't care about errors */
417 talloc_free(call);
421 called when we get a new connection
423 static void ntp_signd_accept(struct stream_connection *conn)
425 struct ntp_signd_server *ntp_signd = talloc_get_type(conn->private_data,
426 struct ntp_signd_server);
427 struct ntp_signd_connection *ntp_signd_conn;
428 struct tevent_req *subreq;
429 int rc;
431 ntp_signd_conn = talloc_zero(conn, struct ntp_signd_connection);
432 if (ntp_signd_conn == NULL) {
433 stream_terminate_connection(conn,
434 "ntp_signd_accept: out of memory");
435 return;
438 ntp_signd_conn->send_queue = tevent_queue_create(conn,
439 "ntp_signd_accept");
440 if (ntp_signd_conn->send_queue == NULL) {
441 stream_terminate_connection(conn,
442 "ntp_signd_accept: out of memory");
443 return;
446 TALLOC_FREE(conn->event.fde);
448 rc = tstream_bsd_existing_socket(ntp_signd_conn->tstream,
449 socket_get_fd(conn->socket),
450 &ntp_signd_conn->tstream);
451 if (rc < 0) {
452 stream_terminate_connection(conn,
453 "ntp_signd_accept: out of memory");
454 return;
457 ntp_signd_conn->conn = conn;
458 ntp_signd_conn->ntp_signd = ntp_signd;
459 conn->private_data = ntp_signd_conn;
462 * The NTP tcp pdu's has the length as 4 byte (initial_read_size),
463 * packet_full_request_u32 provides the pdu length then.
465 subreq = tstream_read_pdu_blob_send(ntp_signd_conn,
466 ntp_signd_conn->conn->event.ctx,
467 ntp_signd_conn->tstream,
468 4, /* initial_read_size */
469 packet_full_request_u32,
470 ntp_signd_conn);
471 if (subreq == NULL) {
472 ntp_signd_terminate_connection(ntp_signd_conn,
473 "ntp_signd_accept: "
474 "no memory for tstream_read_pdu_blob_send");
475 return;
477 tevent_req_set_callback(subreq, ntp_signd_call_loop, ntp_signd_conn);
480 static const struct stream_server_ops ntp_signd_stream_ops = {
481 .name = "ntp_signd",
482 .accept_connection = ntp_signd_accept,
483 .recv_handler = ntp_signd_recv,
484 .send_handler = ntp_signd_send
488 startup the ntp_signd task
490 static void ntp_signd_task_init(struct task_server *task)
492 struct ntp_signd_server *ntp_signd;
493 NTSTATUS status;
495 const struct model_ops *model_ops;
497 const char *address;
499 if (!directory_create_or_exist(lp_ntp_signd_socket_directory(task->lp_ctx), geteuid(), 0755)) {
500 char *error = talloc_asprintf(task, "Cannot create NTP signd pipe directory: %s",
501 lp_ntp_signd_socket_directory(task->lp_ctx));
502 task_server_terminate(task,
503 error, true);
504 return;
507 /* within the ntp_signd task we want to be a single process, so
508 ask for the single process model ops and pass these to the
509 stream_setup_socket() call. */
510 model_ops = process_model_startup(task->event_ctx, "single");
511 if (!model_ops) {
512 DEBUG(0,("Can't find 'single' process model_ops\n"));
513 return;
516 task_server_set_title(task, "task[ntp_signd]");
518 ntp_signd = talloc(task, struct ntp_signd_server);
519 if (ntp_signd == NULL) {
520 task_server_terminate(task, "ntp_signd: out of memory", true);
521 return;
524 ntp_signd->task = task;
526 /* Must be system to get at the password hashes */
527 ntp_signd->samdb = samdb_connect(ntp_signd, task->event_ctx, task->lp_ctx, system_session(task->lp_ctx));
528 if (ntp_signd->samdb == NULL) {
529 task_server_terminate(task, "ntp_signd failed to open samdb", true);
530 return;
533 address = talloc_asprintf(ntp_signd, "%s/socket", lp_ntp_signd_socket_directory(task->lp_ctx));
535 status = stream_setup_socket(ntp_signd->task->event_ctx,
536 ntp_signd->task->lp_ctx,
537 model_ops,
538 &ntp_signd_stream_ops,
539 "unix", address, NULL,
540 lp_socket_options(ntp_signd->task->lp_ctx),
541 ntp_signd);
542 if (!NT_STATUS_IS_OK(status)) {
543 DEBUG(0,("Failed to bind to %s - %s\n",
544 address, nt_errstr(status)));
545 return;
551 /* called at smbd startup - register ourselves as a server service */
552 NTSTATUS server_service_ntp_signd_init(void)
554 return register_server_service("ntp_signd", ntp_signd_task_init);