Merge branch 'v4-0-test' of ssh://git.samba.org/data/git/samba into 4-0-abartlet
[gd/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 "librpc/gen_ndr/ndr_ntp_signd.h"
31 #include "param/param.h"
32 #include "dsdb/samdb/samdb.h"
33 #include "auth/auth.h"
34 #include "libcli/security/security.h"
35 #include "lib/ldb/include/ldb.h"
36 #include "lib/ldb/include/ldb_errors.h"
37
38 /*
39   top level context structure for the ntp_signd server
40 */
41 struct ntp_signd_server {
42         struct task_server *task;
43         struct ldb_context *samdb;
44 };
45
46 /*
47   state of an open connection
48 */
49 struct ntp_signd_connection {
50         /* stream connection we belong to */
51         struct stream_connection *conn;
52
53         /* the ntp_signd_server the connection belongs to */
54         struct ntp_signd_server *ntp_signd;
55
56         struct packet_context *packet;
57 };
58
59 static void ntp_signd_terminate_connection(struct ntp_signd_connection *ntp_signdconn, const char *reason)
60 {
61         stream_terminate_connection(ntp_signdconn->conn, reason);
62 }
63
64 /*
65   receive a full packet on a NTP_SIGND connection
66 */
67 static NTSTATUS ntp_signd_recv(void *private, DATA_BLOB blob)
68 {
69         struct ntp_signd_connection *ntp_signdconn = talloc_get_type(private, 
70                                                              struct ntp_signd_connection);
71         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
72         TALLOC_CTX *tmp_ctx = talloc_new(ntp_signdconn);
73         DATA_BLOB input, reply;
74         const struct dom_sid *domain_sid;
75         struct dom_sid *sid;
76         struct sign_request sign_request;
77         enum ndr_err_code ndr_err;
78         struct ldb_result *res;
79         const char *attrs[] = { "unicodePwd", NULL };
80         int ret;
81
82         talloc_steal(tmp_ctx, blob.data);
83
84         input = data_blob_const(blob.data + 4, blob.length - 4); 
85
86         ndr_err = ndr_pull_struct_blob_all(&input, tmp_ctx, 
87                                            lp_iconv_convenience(ntp_signdconn->ntp_signd->task->lp_ctx),
88                                            &sign_request,
89                                            (ndr_pull_flags_fn_t)ndr_pull_sign_request);
90
91         if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
92                 DEBUG(1,("failed to parse ntp signing request\n"));
93                 dump_data(1, input.data, input.length);
94                 return ndr_map_error2ntstatus(ndr_err);
95         }
96
97         domain_sid = samdb_domain_sid(ntp_signdconn->ntp_signd->samdb);
98         if (!domain_sid) {
99                 return NT_STATUS_INVALID_PARAMETER;
100         }
101         
102         sid = dom_sid_add_rid(tmp_ctx, domain_sid, sign_request.key_id & 0x7FFFFFFF);
103         if (!sid) {
104                 return NT_STATUS_NO_MEMORY;
105         }
106
107         /* Sign packet */
108         ret = ldb_search_exp_fmt(ntp_signdconn->ntp_signd->samdb, tmp_ctx,
109                                  &res, samdb_base_dn(ntp_signdconn->ntp_signd->samdb),
110                                  LDB_SCOPE_SUBTREE, attrs, "(&(objectSid=%s)(objectClass=computer))",
111                                  dom_sid_string(tmp_ctx, sid));
112         if (ret != LDB_SUCCESS) {
113                 return NT_STATUS_UNSUCCESSFUL;
114         }
115
116         if (res->count != 1) {
117                 return NT_STATUS_NO_SUCH_USER;
118         }
119
120         /* Sign the NTP response with the unicodePwd */
121
122         /* Place it into the packet for the wire */
123
124         blob = data_blob_talloc(ntp_signdconn, NULL, reply.length + 4);
125         if (!blob.data) {
126                 talloc_free(tmp_ctx);
127                 return NT_STATUS_NO_MEMORY;
128         }
129
130         RSIVAL(blob.data, 0, reply.length);
131         memcpy(blob.data + 4, reply.data, reply.length);        
132
133         status = packet_send(ntp_signdconn->packet, blob);
134
135         /* the call isn't needed any more */
136         talloc_free(tmp_ctx);
137         return status;
138 }
139
140 /*
141   receive some data on a NTP_SIGND connection
142 */
143 static void ntp_signd_recv_handler(struct stream_connection *conn, uint16_t flags)
144 {
145         struct ntp_signd_connection *ntp_signdconn = talloc_get_type(conn->private, 
146                                                              struct ntp_signd_connection);
147         packet_recv(ntp_signdconn->packet);
148 }
149
150 /*
151   called on a tcp recv error
152 */
153 static void ntp_signd_recv_error(void *private, NTSTATUS status)
154 {
155         struct ntp_signd_connection *ntp_signdconn = talloc_get_type(private, struct ntp_signd_connection);
156         ntp_signd_terminate_connection(ntp_signdconn, nt_errstr(status));
157 }
158
159 /*
160   called when we can write to a connection
161 */
162 static void ntp_signd_send(struct stream_connection *conn, uint16_t flags)
163 {
164         struct ntp_signd_connection *ntp_signdconn = talloc_get_type(conn->private, 
165                                                              struct ntp_signd_connection);
166         packet_queue_run(ntp_signdconn->packet);
167 }
168
169 /*
170   called when we get a new connection
171 */
172 static void ntp_signd_accept(struct stream_connection *conn)
173 {
174         struct ntp_signd_server *ntp_signd = talloc_get_type(conn->private, struct ntp_signd_server);
175         struct ntp_signd_connection *ntp_signdconn;
176
177         ntp_signdconn = talloc_zero(conn, struct ntp_signd_connection);
178         if (!ntp_signdconn) {
179                 stream_terminate_connection(conn, "ntp_signd_accept: out of memory");
180                 return;
181         }
182         ntp_signdconn->conn      = conn;
183         ntp_signdconn->ntp_signd         = ntp_signd;
184         conn->private    = ntp_signdconn;
185
186         ntp_signdconn->packet = packet_init(ntp_signdconn);
187         if (ntp_signdconn->packet == NULL) {
188                 ntp_signd_terminate_connection(ntp_signdconn, "ntp_signd_accept: out of memory");
189                 return;
190         }
191         packet_set_private(ntp_signdconn->packet, ntp_signdconn);
192         packet_set_socket(ntp_signdconn->packet, conn->socket);
193         packet_set_callback(ntp_signdconn->packet, ntp_signd_recv);
194         packet_set_full_request(ntp_signdconn->packet, packet_full_request_u32);
195         packet_set_error_handler(ntp_signdconn->packet, ntp_signd_recv_error);
196         packet_set_event_context(ntp_signdconn->packet, conn->event.ctx);
197         packet_set_fde(ntp_signdconn->packet, conn->event.fde);
198         packet_set_serialise(ntp_signdconn->packet);
199 }
200
201 static const struct stream_server_ops ntp_signd_stream_ops = {
202         .name                   = "ntp_signd",
203         .accept_connection      = ntp_signd_accept,
204         .recv_handler           = ntp_signd_recv_handler,
205         .send_handler           = ntp_signd_send
206 };
207
208 /*
209   startup the ntp_signd task
210 */
211 static void ntp_signd_task_init(struct task_server *task)
212 {
213         struct ntp_signd_server *ntp_signd;
214         NTSTATUS status;
215
216         const struct model_ops *model_ops;
217
218         const char *address = "/tmp/ux_demo";
219
220         /* within the ntp_signd task we want to be a single process, so
221            ask for the single process model ops and pass these to the
222            stream_setup_socket() call. */
223         model_ops = process_model_byname("single");
224         if (!model_ops) {
225                 DEBUG(0,("Can't find 'single' process model_ops\n"));
226                 return;
227         }
228
229         task_server_set_title(task, "task[ntp_signd]");
230
231         ntp_signd = talloc(task, struct ntp_signd_server);
232         if (ntp_signd == NULL) {
233                 task_server_terminate(task, "ntp_signd: out of memory");
234                 return;
235         }
236
237         ntp_signd->task = task;
238
239         ntp_signd->samdb = samdb_connect(ntp_signd, task->event_ctx, task->lp_ctx, anonymous_session(ntp_signd, task->event_ctx, task->lp_ctx));
240         if (ntp_signd->samdb == NULL) {
241                 task_server_terminate(task, "ntp_signd failed to open samdb");
242                 return;
243         }
244
245         status = stream_setup_socket(ntp_signd->task->event_ctx, 
246                                      ntp_signd->task->lp_ctx,
247                                      model_ops, 
248                                      &ntp_signd_stream_ops, 
249                                      "unix", address, NULL,
250                                      lp_socket_options(ntp_signd->task->lp_ctx), 
251                                      ntp_signd);
252         if (!NT_STATUS_IS_OK(status)) {
253                 DEBUG(0,("Failed to bind to %s - %s\n",
254                          address, nt_errstr(status)));
255                 return;
256         }
257
258 }
259
260
261 /* called at smbd startup - register ourselves as a server service */
262 NTSTATUS server_service_ntp_signd_init(void)
263 {
264         return register_server_service("ntp_signd", ntp_signd_task_init);
265 }