1 /*
2    Unix SMB/CIFS implementation.
3 
4    KDC related functions
5 
6    Copyright (c) 2005-2008 Andrew Bartlett <abartlet@samba.org>
7    Copyright (c) 2005      Andrew Tridgell <tridge@samba.org>
8    Copyright (c) 2005      Stefan Metzmacher <metze@samba.org>
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 "param/param.h"
26 #include "smbd/process_model.h"
27 #include "lib/tsocket/tsocket.h"
28 #include "libcli/util/tstream.h"
29 #include "kdc/kdc-server.h"
30 #include "kdc/kdc-proxy.h"
31 #include "lib/stream/packet.h"
32 
33 /*
34  * State of an open tcp connection
35  */
36 struct kdc_tcp_connection {
37 	/* stream connection we belong to */
38 	struct stream_connection *conn;
39 
40 	/* the kdc_server the connection belongs to */
41 	struct kdc_socket *kdc_socket;
42 
43 	struct tstream_context *tstream;
44 
45 	struct tevent_queue *send_queue;
46 };
47 
48 struct kdc_tcp_call {
49 	struct kdc_tcp_connection *kdc_conn;
50 	DATA_BLOB in;
51 	DATA_BLOB out;
52 	uint8_t out_hdr[4];
53 	struct iovec out_iov[2];
54 };
55 
56 struct kdc_udp_call {
57 	struct kdc_udp_socket *sock;
58 	struct tsocket_address *src;
59 	DATA_BLOB in;
60 	DATA_BLOB out;
61 };
62 
63 static void kdc_udp_call_proxy_done(struct tevent_req *subreq);
64 static void kdc_udp_call_sendto_done(struct tevent_req *subreq);
65 
66 static void kdc_tcp_call_writev_done(struct tevent_req *subreq);
67 static void kdc_tcp_call_proxy_done(struct tevent_req *subreq);
68 
kdc_tcp_terminate_connection(struct kdc_tcp_connection * kdc_conn,const char * reason)69 static void kdc_tcp_terminate_connection(struct kdc_tcp_connection *kdc_conn,
70 					 const char *reason)
71 {
72 	stream_terminate_connection(kdc_conn->conn, reason);
73 }
74 
kdc_proxy_unavailable_error(struct kdc_server * kdc,TALLOC_CTX * mem_ctx,DATA_BLOB * out)75 static NTSTATUS kdc_proxy_unavailable_error(struct kdc_server *kdc,
76 					    TALLOC_CTX *mem_ctx,
77 					    DATA_BLOB *out)
78 {
79 	krb5_error_code code;
80 	krb5_data enc_error;
81 
82 	code = smb_krb5_mk_error(kdc->smb_krb5_context->krb5_context,
83 				 KRB5KDC_ERR_SVC_UNAVAILABLE,
84 				 NULL,
85 				 NULL,
86 				 NULL,
87 				 NULL,
88 				 &enc_error);
89 	if (code != 0) {
90 		DBG_WARNING("Unable to form krb5 error reply\n");
91 		return NT_STATUS_INTERNAL_ERROR;
92 	}
93 
94 	*out = data_blob_talloc(mem_ctx, enc_error.data, enc_error.length);
95 	smb_krb5_free_data_contents(kdc->smb_krb5_context->krb5_context,
96 				    &enc_error);
97 	if (!out->data) {
98 		return NT_STATUS_NO_MEMORY;
99 	}
100 
101 	return NT_STATUS_OK;
102 }
103 
kdc_udp_call_loop(struct tevent_req * subreq)104 static void kdc_udp_call_loop(struct tevent_req *subreq)
105 {
106 	struct kdc_udp_socket *sock = tevent_req_callback_data(subreq,
107 				      struct kdc_udp_socket);
108 	struct kdc_udp_call *call;
109 	uint8_t *buf;
110 	ssize_t len;
111 	int sys_errno;
112 	kdc_code ret;
113 
114 	call = talloc(sock, struct kdc_udp_call);
115 	if (call == NULL) {
116 		talloc_free(call);
117 		goto done;
118 	}
119 	call->sock = sock;
120 
121 	len = tdgram_recvfrom_recv(subreq, &sys_errno,
122 				   call, &buf, &call->src);
123 	TALLOC_FREE(subreq);
124 	if (len == -1) {
125 		talloc_free(call);
126 		goto done;
127 	}
128 
129 	call->in.data = buf;
130 	call->in.length = len;
131 
132 	DEBUG(10,("Received krb5 UDP packet of length %lu from %s\n",
133 		 (long)call->in.length,
134 		 tsocket_address_string(call->src, call)));
135 
136 	/* Call krb5 */
137 	ret = sock->kdc_socket->process(sock->kdc_socket->kdc,
138 				       call,
139 				       &call->in,
140 				       &call->out,
141 				       call->src,
142 				       sock->kdc_socket->local_address,
143 				       1 /* Datagram */);
144 	if (ret == KDC_ERROR) {
145 		talloc_free(call);
146 		goto done;
147 	}
148 
149 	if (ret == KDC_PROXY_REQUEST) {
150 		uint16_t port;
151 
152 		if (!sock->kdc_socket->kdc->am_rodc) {
153 			DEBUG(0,("kdc_udp_call_loop: proxying requested when not RODC"));
154 			talloc_free(call);
155 			goto done;
156 		}
157 
158 		port = tsocket_address_inet_port(sock->kdc_socket->local_address);
159 
160 		subreq = kdc_udp_proxy_send(call,
161 					    sock->kdc_socket->kdc->task->event_ctx,
162 					    sock->kdc_socket->kdc,
163 					    port,
164 					    call->in);
165 		if (subreq == NULL) {
166 			talloc_free(call);
167 			goto done;
168 		}
169 		tevent_req_set_callback(subreq, kdc_udp_call_proxy_done, call);
170 		goto done;
171 	}
172 
173 	subreq = tdgram_sendto_queue_send(call,
174 					  sock->kdc_socket->kdc->task->event_ctx,
175 					  sock->dgram,
176 					  sock->send_queue,
177 					  call->out.data,
178 					  call->out.length,
179 					  call->src);
180 	if (subreq == NULL) {
181 		talloc_free(call);
182 		goto done;
183 	}
184 	tevent_req_set_callback(subreq, kdc_udp_call_sendto_done, call);
185 
186 done:
187 	subreq = tdgram_recvfrom_send(sock,
188 				      sock->kdc_socket->kdc->task->event_ctx,
189 				      sock->dgram);
190 	if (subreq == NULL) {
191 		task_server_terminate(sock->kdc_socket->kdc->task,
192 				      "no memory for tdgram_recvfrom_send",
193 				      true);
194 		return;
195 	}
196 	tevent_req_set_callback(subreq, kdc_udp_call_loop, sock);
197 }
198 
kdc_udp_call_proxy_done(struct tevent_req * subreq)199 static void kdc_udp_call_proxy_done(struct tevent_req *subreq)
200 {
201 	struct kdc_udp_call *call =
202 		tevent_req_callback_data(subreq,
203 		struct kdc_udp_call);
204 	NTSTATUS status;
205 
206 	status = kdc_udp_proxy_recv(subreq, call, &call->out);
207 	TALLOC_FREE(subreq);
208 	if (!NT_STATUS_IS_OK(status)) {
209 		/* generate an error packet */
210 		status = kdc_proxy_unavailable_error(call->sock->kdc_socket->kdc,
211 						     call, &call->out);
212 	}
213 
214 	if (!NT_STATUS_IS_OK(status)) {
215 		talloc_free(call);
216 		return;
217 	}
218 
219 	subreq = tdgram_sendto_queue_send(call,
220 					  call->sock->kdc_socket->kdc->task->event_ctx,
221 					  call->sock->dgram,
222 					  call->sock->send_queue,
223 					  call->out.data,
224 					  call->out.length,
225 					  call->src);
226 	if (subreq == NULL) {
227 		talloc_free(call);
228 		return;
229 	}
230 
231 	tevent_req_set_callback(subreq, kdc_udp_call_sendto_done, call);
232 }
233 
kdc_udp_call_sendto_done(struct tevent_req * subreq)234 static void kdc_udp_call_sendto_done(struct tevent_req *subreq)
235 {
236 	struct kdc_udp_call *call = tevent_req_callback_data(subreq,
237 				       struct kdc_udp_call);
238 	int sys_errno;
239 
240 	tdgram_sendto_queue_recv(subreq, &sys_errno);
241 
242 	/* We don't care about errors */
243 
244 	talloc_free(call);
245 }
246 
kdc_tcp_call_loop(struct tevent_req * subreq)247 static void kdc_tcp_call_loop(struct tevent_req *subreq)
248 {
249 	struct kdc_tcp_connection *kdc_conn = tevent_req_callback_data(subreq,
250 				      struct kdc_tcp_connection);
251 	struct kdc_tcp_call *call;
252 	NTSTATUS status;
253 	kdc_code ret;
254 
255 	call = talloc(kdc_conn, struct kdc_tcp_call);
256 	if (call == NULL) {
257 		kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_loop: "
258 				"no memory for kdc_tcp_call");
259 		return;
260 	}
261 	call->kdc_conn = kdc_conn;
262 
263 	status = tstream_read_pdu_blob_recv(subreq,
264 					    call,
265 					    &call->in);
266 	TALLOC_FREE(subreq);
267 	if (!NT_STATUS_IS_OK(status)) {
268 		const char *reason;
269 
270 		reason = talloc_asprintf(call, "kdc_tcp_call_loop: "
271 					 "tstream_read_pdu_blob_recv() - %s",
272 					 nt_errstr(status));
273 		if (!reason) {
274 			reason = nt_errstr(status);
275 		}
276 
277 		kdc_tcp_terminate_connection(kdc_conn, reason);
278 		return;
279 	}
280 
281 	DEBUG(10,("Received krb5 TCP packet of length %lu from %s\n",
282 		 (long) call->in.length,
283 		 tsocket_address_string(kdc_conn->conn->remote_address, call)));
284 
285 	/* skip length header */
286 	call->in.data +=4;
287 	call->in.length -= 4;
288 
289 	/* Call krb5 */
290 	ret = kdc_conn->kdc_socket->process(kdc_conn->kdc_socket->kdc,
291 					   call,
292 					   &call->in,
293 					   &call->out,
294 					   kdc_conn->conn->remote_address,
295 					   kdc_conn->conn->local_address,
296 					   0 /* Stream */);
297 	if (ret == KDC_ERROR) {
298 		kdc_tcp_terminate_connection(kdc_conn,
299 				"kdc_tcp_call_loop: process function failed");
300 		return;
301 	}
302 
303 	if (ret == KDC_PROXY_REQUEST) {
304 		uint16_t port;
305 
306 		if (!kdc_conn->kdc_socket->kdc->am_rodc) {
307 			kdc_tcp_terminate_connection(kdc_conn,
308 						     "kdc_tcp_call_loop: proxying requested when not RODC");
309 			return;
310 		}
311 		port = tsocket_address_inet_port(kdc_conn->conn->local_address);
312 
313 		subreq = kdc_tcp_proxy_send(call,
314 					    kdc_conn->conn->event.ctx,
315 					    kdc_conn->kdc_socket->kdc,
316 					    port,
317 					    call->in);
318 		if (subreq == NULL) {
319 			kdc_tcp_terminate_connection(kdc_conn,
320 				"kdc_tcp_call_loop: kdc_tcp_proxy_send failed");
321 			return;
322 		}
323 		tevent_req_set_callback(subreq, kdc_tcp_call_proxy_done, call);
324 		return;
325 	}
326 
327 	/* First add the length of the out buffer */
328 	RSIVAL(call->out_hdr, 0, call->out.length);
329 	call->out_iov[0].iov_base = (char *) call->out_hdr;
330 	call->out_iov[0].iov_len = 4;
331 
332 	call->out_iov[1].iov_base = (char *) call->out.data;
333 	call->out_iov[1].iov_len = call->out.length;
334 
335 	subreq = tstream_writev_queue_send(call,
336 					   kdc_conn->conn->event.ctx,
337 					   kdc_conn->tstream,
338 					   kdc_conn->send_queue,
339 					   call->out_iov, 2);
340 	if (subreq == NULL) {
341 		kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_loop: "
342 				"no memory for tstream_writev_queue_send");
343 		return;
344 	}
345 	tevent_req_set_callback(subreq, kdc_tcp_call_writev_done, call);
346 
347 	/*
348 	 * The krb5 tcp pdu's has the length as 4 byte (initial_read_size),
349 	 * packet_full_request_u32 provides the pdu length then.
350 	 */
351 	subreq = tstream_read_pdu_blob_send(kdc_conn,
352 					    kdc_conn->conn->event.ctx,
353 					    kdc_conn->tstream,
354 					    4, /* initial_read_size */
355 					    packet_full_request_u32,
356 					    kdc_conn);
357 	if (subreq == NULL) {
358 		kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_loop: "
359 				"no memory for tstream_read_pdu_blob_send");
360 		return;
361 	}
362 	tevent_req_set_callback(subreq, kdc_tcp_call_loop, kdc_conn);
363 }
364 
kdc_tcp_call_proxy_done(struct tevent_req * subreq)365 static void kdc_tcp_call_proxy_done(struct tevent_req *subreq)
366 {
367 	struct kdc_tcp_call *call = tevent_req_callback_data(subreq,
368 			struct kdc_tcp_call);
369 	struct kdc_tcp_connection *kdc_conn = call->kdc_conn;
370 	NTSTATUS status;
371 
372 	status = kdc_tcp_proxy_recv(subreq, call, &call->out);
373 	TALLOC_FREE(subreq);
374 	if (!NT_STATUS_IS_OK(status)) {
375 		/* generate an error packet */
376 		status = kdc_proxy_unavailable_error(kdc_conn->kdc_socket->kdc,
377 						     call, &call->out);
378 	}
379 
380 	if (!NT_STATUS_IS_OK(status)) {
381 		const char *reason;
382 
383 		reason = talloc_asprintf(call, "kdc_tcp_call_proxy_done: "
384 					 "kdc_proxy_unavailable_error - %s",
385 					 nt_errstr(status));
386 		if (!reason) {
387 			reason = "kdc_tcp_call_proxy_done: kdc_proxy_unavailable_error() failed";
388 		}
389 
390 		kdc_tcp_terminate_connection(call->kdc_conn, reason);
391 		return;
392 	}
393 
394 	/* First add the length of the out buffer */
395 	RSIVAL(call->out_hdr, 0, call->out.length);
396 	call->out_iov[0].iov_base = (char *) call->out_hdr;
397 	call->out_iov[0].iov_len = 4;
398 
399 	call->out_iov[1].iov_base = (char *) call->out.data;
400 	call->out_iov[1].iov_len = call->out.length;
401 
402 	subreq = tstream_writev_queue_send(call,
403 					   kdc_conn->conn->event.ctx,
404 					   kdc_conn->tstream,
405 					   kdc_conn->send_queue,
406 					   call->out_iov, 2);
407 	if (subreq == NULL) {
408 		kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_loop: "
409 				"no memory for tstream_writev_queue_send");
410 		return;
411 	}
412 	tevent_req_set_callback(subreq, kdc_tcp_call_writev_done, call);
413 
414 	/*
415 	 * The krb5 tcp pdu's has the length as 4 byte (initial_read_size),
416 	 * packet_full_request_u32 provides the pdu length then.
417 	 */
418 	subreq = tstream_read_pdu_blob_send(kdc_conn,
419 					    kdc_conn->conn->event.ctx,
420 					    kdc_conn->tstream,
421 					    4, /* initial_read_size */
422 					    packet_full_request_u32,
423 					    kdc_conn);
424 	if (subreq == NULL) {
425 		kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_call_loop: "
426 				"no memory for tstream_read_pdu_blob_send");
427 		return;
428 	}
429 	tevent_req_set_callback(subreq, kdc_tcp_call_loop, kdc_conn);
430 }
431 
kdc_tcp_call_writev_done(struct tevent_req * subreq)432 static void kdc_tcp_call_writev_done(struct tevent_req *subreq)
433 {
434 	struct kdc_tcp_call *call = tevent_req_callback_data(subreq,
435 			struct kdc_tcp_call);
436 	int sys_errno;
437 	int rc;
438 
439 	rc = tstream_writev_queue_recv(subreq, &sys_errno);
440 	TALLOC_FREE(subreq);
441 	if (rc == -1) {
442 		const char *reason;
443 
444 		reason = talloc_asprintf(call, "kdc_tcp_call_writev_done: "
445 					 "tstream_writev_queue_recv() - %d:%s",
446 					 sys_errno, strerror(sys_errno));
447 		if (!reason) {
448 			reason = "kdc_tcp_call_writev_done: tstream_writev_queue_recv() failed";
449 		}
450 
451 		kdc_tcp_terminate_connection(call->kdc_conn, reason);
452 		return;
453 	}
454 
455 	/* We don't care about errors */
456 
457 	talloc_free(call);
458 }
459 
460 /*
461   called when we get a new connection
462 */
kdc_tcp_accept(struct stream_connection * conn)463 static void kdc_tcp_accept(struct stream_connection *conn)
464 {
465 	struct kdc_socket *kdc_socket;
466 	struct kdc_tcp_connection *kdc_conn;
467 	struct tevent_req *subreq;
468 	int rc;
469 
470 	kdc_conn = talloc_zero(conn, struct kdc_tcp_connection);
471 	if (kdc_conn == NULL) {
472 		stream_terminate_connection(conn,
473 				"kdc_tcp_accept: out of memory");
474 		return;
475 	}
476 
477 	kdc_conn->send_queue = tevent_queue_create(conn, "kdc_tcp_accept");
478 	if (kdc_conn->send_queue == NULL) {
479 		stream_terminate_connection(conn,
480 				"kdc_tcp_accept: out of memory");
481 		return;
482 	}
483 
484 	kdc_socket = talloc_get_type(conn->private_data, struct kdc_socket);
485 
486 	TALLOC_FREE(conn->event.fde);
487 
488 	rc = tstream_bsd_existing_socket(kdc_conn,
489 			socket_get_fd(conn->socket),
490 			&kdc_conn->tstream);
491 	if (rc < 0) {
492 		stream_terminate_connection(conn,
493 				"kdc_tcp_accept: out of memory");
494 		return;
495 	}
496 
497 	kdc_conn->conn = conn;
498 	kdc_conn->kdc_socket = kdc_socket;
499 	conn->private_data = kdc_conn;
500 
501 	/*
502 	 * The krb5 tcp pdu's has the length as 4 byte (initial_read_size),
503 	 * packet_full_request_u32 provides the pdu length then.
504 	 */
505 	subreq = tstream_read_pdu_blob_send(kdc_conn,
506 					    kdc_conn->conn->event.ctx,
507 					    kdc_conn->tstream,
508 					    4, /* initial_read_size */
509 					    packet_full_request_u32,
510 					    kdc_conn);
511 	if (subreq == NULL) {
512 		kdc_tcp_terminate_connection(kdc_conn, "kdc_tcp_accept: "
513 				"no memory for tstream_read_pdu_blob_send");
514 		return;
515 	}
516 	tevent_req_set_callback(subreq, kdc_tcp_call_loop, kdc_conn);
517 }
518 
kdc_tcp_recv(struct stream_connection * conn,uint16_t flags)519 static void kdc_tcp_recv(struct stream_connection *conn, uint16_t flags)
520 {
521 	struct kdc_tcp_connection *kdcconn = talloc_get_type(conn->private_data,
522 							     struct kdc_tcp_connection);
523 	/* this should never be triggered! */
524 	kdc_tcp_terminate_connection(kdcconn, "kdc_tcp_recv: called");
525 }
526 
kdc_tcp_send(struct stream_connection * conn,uint16_t flags)527 static void kdc_tcp_send(struct stream_connection *conn, uint16_t flags)
528 {
529 	struct kdc_tcp_connection *kdcconn = talloc_get_type(conn->private_data,
530 							     struct kdc_tcp_connection);
531 	/* this should never be triggered! */
532 	kdc_tcp_terminate_connection(kdcconn, "kdc_tcp_send: called");
533 }
534 
535 static const struct stream_server_ops kdc_tcp_stream_ops = {
536 	.name			= "kdc_tcp",
537 	.accept_connection	= kdc_tcp_accept,
538 	.recv_handler		= kdc_tcp_recv,
539 	.send_handler		= kdc_tcp_send
540 };
541 
542 /*
543  * Start listening on the given address
544  */
kdc_add_socket(struct kdc_server * kdc,const struct model_ops * model_ops,const char * name,const char * address,uint16_t port,kdc_process_fn_t process,bool udp_only)545 NTSTATUS kdc_add_socket(struct kdc_server *kdc,
546 			const struct model_ops *model_ops,
547 			const char *name,
548 			const char *address,
549 			uint16_t port,
550 			kdc_process_fn_t process,
551 			bool udp_only)
552 {
553 	struct kdc_socket *kdc_socket;
554 	struct kdc_udp_socket *kdc_udp_socket;
555 	struct tevent_req *udpsubreq;
556 	NTSTATUS status;
557 	int ret;
558 
559 	kdc_socket = talloc(kdc, struct kdc_socket);
560 	NT_STATUS_HAVE_NO_MEMORY(kdc_socket);
561 
562 	kdc_socket->kdc = kdc;
563 	kdc_socket->process = process;
564 
565 	ret = tsocket_address_inet_from_strings(kdc_socket, "ip",
566 						address, port,
567 						&kdc_socket->local_address);
568 	if (ret != 0) {
569 		status = map_nt_error_from_unix_common(errno);
570 		return status;
571 	}
572 
573 	if (!udp_only) {
574 		status = stream_setup_socket(kdc->task,
575 					     kdc->task->event_ctx,
576 					     kdc->task->lp_ctx,
577 					     model_ops,
578 					     &kdc_tcp_stream_ops,
579 					     "ip", address, &port,
580 					     lpcfg_socket_options(kdc->task->lp_ctx),
581 					     kdc_socket,
582 					     kdc->task->process_context);
583 		if (!NT_STATUS_IS_OK(status)) {
584 			DEBUG(0,("Failed to bind to %s:%u TCP - %s\n",
585 				 address, port, nt_errstr(status)));
586 			talloc_free(kdc_socket);
587 			return status;
588 		}
589 	}
590 
591 	kdc_udp_socket = talloc(kdc_socket, struct kdc_udp_socket);
592 	NT_STATUS_HAVE_NO_MEMORY(kdc_udp_socket);
593 
594 	kdc_udp_socket->kdc_socket = kdc_socket;
595 
596 	ret = tdgram_inet_udp_socket(kdc_socket->local_address,
597 				     NULL,
598 				     kdc_udp_socket,
599 				     &kdc_udp_socket->dgram);
600 	if (ret != 0) {
601 		status = map_nt_error_from_unix_common(errno);
602 		DEBUG(0,("Failed to bind to %s:%u UDP - %s\n",
603 			 address, port, nt_errstr(status)));
604 		return status;
605 	}
606 
607 	kdc_udp_socket->send_queue = tevent_queue_create(kdc_udp_socket,
608 							 "kdc_udp_send_queue");
609 	NT_STATUS_HAVE_NO_MEMORY(kdc_udp_socket->send_queue);
610 
611 	udpsubreq = tdgram_recvfrom_send(kdc_udp_socket,
612 					 kdc->task->event_ctx,
613 					 kdc_udp_socket->dgram);
614 	NT_STATUS_HAVE_NO_MEMORY(udpsubreq);
615 	tevent_req_set_callback(udpsubreq, kdc_udp_call_loop, kdc_udp_socket);
616 
617 	return NT_STATUS_OK;
618 }
619