source4/: Fix prototypes for all functions in various subsystems.
[sfrench/samba-autobuild/.git] / source4 / ntp_signd / ntp_signd.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    NTP packet signing server
5
6    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2005
7    Copyright (C) Andrew Tridgell        2005
8    Copyright (C) Stefan Metzmacher      2005
9
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.
14    
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.
19    
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/>.
22 */
23
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 "libcli/ldap/ldap_ndr.h"
38 #include <ldb.h>
39 #include <ldb_errors.h>
40 #include "../lib/crypto/md5.h"
41 #include "system/network.h"
42 #include "system/passwd.h"
43
44 NTSTATUS server_service_ntp_signd_init(void);
45
46 /*
47   top level context structure for the ntp_signd server
48 */
49 struct ntp_signd_server {
50         struct task_server *task;
51         struct ldb_context *samdb;
52 };
53
54 /*
55   state of an open connection
56 */
57 struct ntp_signd_connection {
58         /* stream connection we belong to */
59         struct stream_connection *conn;
60
61         /* the ntp_signd_server the connection belongs to */
62         struct ntp_signd_server *ntp_signd;
63
64         struct tstream_context *tstream;
65
66         struct tevent_queue *send_queue;
67 };
68
69 static void ntp_signd_terminate_connection(struct ntp_signd_connection *ntp_signd_conn, const char *reason)
70 {
71         stream_terminate_connection(ntp_signd_conn->conn, reason);
72 }
73
74 static NTSTATUS signing_failure(struct ntp_signd_connection *ntp_signdconn,
75                                 TALLOC_CTX *mem_ctx,
76                                 DATA_BLOB *output,
77                                 uint32_t packet_id)
78 {
79         struct signed_reply signed_reply;
80         enum ndr_err_code ndr_err;
81
82         signed_reply.op = SIGNING_FAILURE;
83         signed_reply.packet_id = packet_id;
84         signed_reply.signed_packet = data_blob(NULL, 0);
85         
86         ndr_err = ndr_push_struct_blob(output, mem_ctx, &signed_reply,
87                                        (ndr_push_flags_fn_t)ndr_push_signed_reply);
88
89         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
90                 DEBUG(1,("failed to push ntp error reply\n"));
91                 return ndr_map_error2ntstatus(ndr_err);
92         }
93
94         return NT_STATUS_OK;
95 }
96
97 /*
98   receive a full packet on a NTP_SIGND connection
99 */
100 static NTSTATUS ntp_signd_process(struct ntp_signd_connection *ntp_signd_conn,
101                                   TALLOC_CTX *mem_ctx,
102                                   DATA_BLOB *input,
103                                   DATA_BLOB *output)
104 {
105         const struct dom_sid *domain_sid;
106         struct dom_sid *sid;
107         struct sign_request sign_request;
108         struct signed_reply signed_reply;
109         enum ndr_err_code ndr_err;
110         struct ldb_result *res;
111         const char *attrs[] = { "unicodePwd", "userAccountControl", "cn", NULL };
112         struct MD5Context ctx;
113         struct samr_Password *nt_hash;
114         uint32_t user_account_control;
115         int ret;
116
117         ndr_err = ndr_pull_struct_blob_all(input, mem_ctx,
118                                            &sign_request,
119                                            (ndr_pull_flags_fn_t)ndr_pull_sign_request);
120
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);
125         }
126
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);
134         }
135
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);
143         }
144
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);
151         }
152         
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);
162         }
163
164         ret = ldb_search(ntp_signd_conn->ntp_signd->samdb, mem_ctx,
165                                  &res,
166                                  ldb_get_default_basedn(ntp_signd_conn->ntp_signd->samdb),
167                                  LDB_SCOPE_SUBTREE,
168                                  attrs,
169                                  "(&(objectSid=%s)(objectClass=user))",
170                                  ldap_encode_ndr_dom_sid(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);
180         }
181
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);
192         }
193
194         user_account_control = ldb_msg_find_attr_as_uint(res->msgs[0],
195                                                          "userAccountControl",
196                                                          0);
197
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;
203         }
204
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;
210         }
211
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);
220         }
221
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);
228
229         if (!signed_reply.signed_packet.data) {
230                 return signing_failure(ntp_signd_conn,
231                                        mem_ctx,
232                                        output,
233                                        sign_request.packet_id);
234         }
235
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);
238
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);
244
245
246         /* Place it into the packet for the wire */
247         ndr_err = ndr_push_struct_blob(output, mem_ctx, &signed_reply,
248                                        (ndr_push_flags_fn_t)ndr_push_signed_reply);
249
250         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
251                 DEBUG(1,("failed to push ntp error reply\n"));
252                 return ndr_map_error2ntstatus(ndr_err);
253         }
254
255         return NT_STATUS_OK;
256 }
257
258 /*
259   called on a tcp recv
260 */
261 static void ntp_signd_recv(struct stream_connection *conn, uint16_t flags)
262 {
263         struct ntp_signd_connection *ntp_signd_conn = talloc_get_type(conn->private_data,
264                                                         struct ntp_signd_connection);
265         ntp_signd_terminate_connection(ntp_signd_conn,
266                                        "ntp_signd_recv: called");
267 }
268
269 /*
270   called when we can write to a connection
271 */
272 static void ntp_signd_send(struct stream_connection *conn, uint16_t flags)
273 {
274         struct ntp_signd_connection *ntp_signd_conn = talloc_get_type(conn->private_data,
275                                                         struct ntp_signd_connection);
276         /* this should never be triggered! */
277         ntp_signd_terminate_connection(ntp_signd_conn,
278                                        "ntp_signd_send: called");
279 }
280
281 struct ntp_signd_call {
282         struct ntp_signd_connection *ntp_signd_conn;
283         DATA_BLOB in;
284         DATA_BLOB out;
285         uint8_t out_hdr[4];
286         struct iovec out_iov[2];
287 };
288
289 static void ntp_signd_call_writev_done(struct tevent_req *subreq);
290
291 static void ntp_signd_call_loop(struct tevent_req *subreq)
292 {
293         struct ntp_signd_connection *ntp_signd_conn = tevent_req_callback_data(subreq,
294                                       struct ntp_signd_connection);
295         struct ntp_signd_call *call;
296         NTSTATUS status;
297
298         call = talloc(ntp_signd_conn, struct ntp_signd_call);
299         if (call == NULL) {
300                 ntp_signd_terminate_connection(ntp_signd_conn,
301                                 "ntp_signd_call_loop: "
302                                 "no memory for ntp_signd_call");
303                 return;
304         }
305         call->ntp_signd_conn = ntp_signd_conn;
306
307         status = tstream_read_pdu_blob_recv(subreq,
308                                             call,
309                                             &call->in);
310         TALLOC_FREE(subreq);
311         if (!NT_STATUS_IS_OK(status)) {
312                 const char *reason;
313
314                 reason = talloc_asprintf(call, "ntp_signd_call_loop: "
315                                          "tstream_read_pdu_blob_recv() - %s",
316                                          nt_errstr(status));
317                 if (reason == NULL) {
318                         reason = nt_errstr(status);
319                 }
320
321                 ntp_signd_terminate_connection(ntp_signd_conn, reason);
322                 return;
323         }
324
325         DEBUG(10,("Received NTP TCP packet of length %lu from %s\n",
326                  (long) call->in.length,
327                  tsocket_address_string(ntp_signd_conn->conn->remote_address, call)));
328
329         /* skip length header */
330         call->in.data +=4;
331         call->in.length -= 4;
332
333         status = ntp_signd_process(ntp_signd_conn,
334                                      call,
335                                      &call->in,
336                                      &call->out);
337         if (! NT_STATUS_IS_OK(status)) {
338                 const char *reason;
339
340                 reason = talloc_asprintf(call, "ntp_signd_process failed: %s",
341                                          nt_errstr(status));
342                 if (reason == NULL) {
343                         reason = nt_errstr(status);
344                 }
345
346                 ntp_signd_terminate_connection(ntp_signd_conn, reason);
347                 return;
348         }
349
350         /* First add the length of the out buffer */
351         RSIVAL(call->out_hdr, 0, call->out.length);
352         call->out_iov[0].iov_base = (char *) call->out_hdr;
353         call->out_iov[0].iov_len = 4;
354
355         call->out_iov[1].iov_base = (char *) call->out.data;
356         call->out_iov[1].iov_len = call->out.length;
357
358         subreq = tstream_writev_queue_send(call,
359                                            ntp_signd_conn->conn->event.ctx,
360                                            ntp_signd_conn->tstream,
361                                            ntp_signd_conn->send_queue,
362                                            call->out_iov, 2);
363         if (subreq == NULL) {
364                 ntp_signd_terminate_connection(ntp_signd_conn, "ntp_signd_call_loop: "
365                                 "no memory for tstream_writev_queue_send");
366                 return;
367         }
368
369         tevent_req_set_callback(subreq, ntp_signd_call_writev_done, call);
370
371         /*
372          * The NTP tcp pdu's has the length as 4 byte (initial_read_size),
373          * packet_full_request_u32 provides the pdu length then.
374          */
375         subreq = tstream_read_pdu_blob_send(ntp_signd_conn,
376                                             ntp_signd_conn->conn->event.ctx,
377                                             ntp_signd_conn->tstream,
378                                             4, /* initial_read_size */
379                                             packet_full_request_u32,
380                                             ntp_signd_conn);
381         if (subreq == NULL) {
382                 ntp_signd_terminate_connection(ntp_signd_conn, "ntp_signd_call_loop: "
383                                 "no memory for tstream_read_pdu_blob_send");
384                 return;
385         }
386         tevent_req_set_callback(subreq, ntp_signd_call_loop, ntp_signd_conn);
387 }
388
389 static void ntp_signd_call_writev_done(struct tevent_req *subreq)
390 {
391         struct ntp_signd_call *call = tevent_req_callback_data(subreq,
392                         struct ntp_signd_call);
393         int sys_errno;
394         int rc;
395
396         rc = tstream_writev_queue_recv(subreq, &sys_errno);
397         TALLOC_FREE(subreq);
398         if (rc == -1) {
399                 const char *reason;
400
401                 reason = talloc_asprintf(call, "ntp_signd_call_writev_done: "
402                                          "tstream_writev_queue_recv() - %d:%s",
403                                          sys_errno, strerror(sys_errno));
404                 if (!reason) {
405                         reason = "ntp_signd_call_writev_done: "
406                                  "tstream_writev_queue_recv() failed";
407                 }
408
409                 ntp_signd_terminate_connection(call->ntp_signd_conn, reason);
410                 return;
411         }
412
413         /* We don't care about errors */
414
415         talloc_free(call);
416 }
417
418 /*
419   called when we get a new connection
420 */
421 static void ntp_signd_accept(struct stream_connection *conn)
422 {
423         struct ntp_signd_server *ntp_signd = talloc_get_type(conn->private_data,
424                                                 struct ntp_signd_server);
425         struct ntp_signd_connection *ntp_signd_conn;
426         struct tevent_req *subreq;
427         int rc;
428
429         ntp_signd_conn = talloc_zero(conn, struct ntp_signd_connection);
430         if (ntp_signd_conn == NULL) {
431                 stream_terminate_connection(conn,
432                                 "ntp_signd_accept: out of memory");
433                 return;
434         }
435
436         ntp_signd_conn->send_queue = tevent_queue_create(conn,
437                         "ntp_signd_accept");
438         if (ntp_signd_conn->send_queue == NULL) {
439                 stream_terminate_connection(conn,
440                                 "ntp_signd_accept: out of memory");
441                 return;
442         }
443
444         TALLOC_FREE(conn->event.fde);
445
446         rc = tstream_bsd_existing_socket(ntp_signd_conn,
447                         socket_get_fd(conn->socket),
448                         &ntp_signd_conn->tstream);
449         if (rc < 0) {
450                 stream_terminate_connection(conn,
451                                 "ntp_signd_accept: out of memory");
452                 return;
453         }
454
455         ntp_signd_conn->conn = conn;
456         ntp_signd_conn->ntp_signd = ntp_signd;
457         conn->private_data = ntp_signd_conn;
458
459         /*
460          * The NTP tcp pdu's has the length as 4 byte (initial_read_size),
461          * packet_full_request_u32 provides the pdu length then.
462          */
463         subreq = tstream_read_pdu_blob_send(ntp_signd_conn,
464                                             ntp_signd_conn->conn->event.ctx,
465                                             ntp_signd_conn->tstream,
466                                             4, /* initial_read_size */
467                                             packet_full_request_u32,
468                                             ntp_signd_conn);
469         if (subreq == NULL) {
470                 ntp_signd_terminate_connection(ntp_signd_conn,
471                                 "ntp_signd_accept: "
472                                 "no memory for tstream_read_pdu_blob_send");
473                 return;
474         }
475         tevent_req_set_callback(subreq, ntp_signd_call_loop, ntp_signd_conn);
476 }
477
478 static const struct stream_server_ops ntp_signd_stream_ops = {
479         .name                   = "ntp_signd",
480         .accept_connection      = ntp_signd_accept,
481         .recv_handler           = ntp_signd_recv,
482         .send_handler           = ntp_signd_send
483 };
484
485 /*
486   startup the ntp_signd task
487 */
488 static void ntp_signd_task_init(struct task_server *task)
489 {
490         struct ntp_signd_server *ntp_signd;
491         NTSTATUS status;
492
493         const struct model_ops *model_ops;
494
495         const char *address;
496
497         if (!directory_create_or_exist(lpcfg_ntp_signd_socket_directory(task->lp_ctx), geteuid(), 0755)) {
498                 char *error = talloc_asprintf(task, "Cannot create NTP signd pipe directory: %s", 
499                                               lpcfg_ntp_signd_socket_directory(task->lp_ctx));
500                 task_server_terminate(task,
501                                       error, true);
502                 return;
503         }
504
505         /* within the ntp_signd task we want to be a single process, so
506            ask for the single process model ops and pass these to the
507            stream_setup_socket() call. */
508         model_ops = process_model_startup("single");
509         if (!model_ops) {
510                 DEBUG(0,("Can't find 'single' process model_ops\n"));
511                 return;
512         }
513
514         task_server_set_title(task, "task[ntp_signd]");
515
516         ntp_signd = talloc(task, struct ntp_signd_server);
517         if (ntp_signd == NULL) {
518                 task_server_terminate(task, "ntp_signd: out of memory", true);
519                 return;
520         }
521
522         ntp_signd->task = task;
523
524         /* Must be system to get at the password hashes */
525         ntp_signd->samdb = samdb_connect(ntp_signd, task->event_ctx, task->lp_ctx, system_session(task->lp_ctx), 0);
526         if (ntp_signd->samdb == NULL) {
527                 task_server_terminate(task, "ntp_signd failed to open samdb", true);
528                 return;
529         }
530
531         address = talloc_asprintf(ntp_signd, "%s/socket", lpcfg_ntp_signd_socket_directory(task->lp_ctx));
532
533         status = stream_setup_socket(ntp_signd->task,
534                                      ntp_signd->task->event_ctx,
535                                      ntp_signd->task->lp_ctx,
536                                      model_ops, 
537                                      &ntp_signd_stream_ops, 
538                                      "unix", address, NULL,
539                                      lpcfg_socket_options(ntp_signd->task->lp_ctx),
540                                      ntp_signd);
541         if (!NT_STATUS_IS_OK(status)) {
542                 DEBUG(0,("Failed to bind to %s - %s\n",
543                          address, nt_errstr(status)));
544                 return;
545         }
546
547 }
548
549
550 /* called at smbd startup - register ourselves as a server service */
551 NTSTATUS server_service_ntp_signd_init(void)
552 {
553         return register_server_service("ntp_signd", ntp_signd_task_init);
554 }